gpt4 book ai didi

javascript - THREE.js 中自定义网格的变形目标动画

转载 作者:行者123 更新时间:2023-11-28 19:31:37 26 4
gpt4 key购买 nike

我正在创建一个动画,该动画显示 2D 函数绕轴的旋转以创建 3D 表面。我已经能够成功渲染表面,现在我正在尝试使用 MorphTargets 创建动画部分。

不幸的是,虽然我已经成功地将所有变形帧推送到我的几何体中,但我在播放动画时遇到了困难。我发现的所有动画示例都使用 blender 导入模型,因此并不完全有帮助(许多也已经过时)。

我以变形马为例( http://threejs.org/examples/#webgl_morphtargets_horse ),并尝试尽可能多地复制代码,但没有成功。

这是我初始化 morphVerticeHolder 的代码,它是一个用于保存每个动画帧的顶点的 2D 数组

 //First indices of multiarray corresponds to morph frame, second to the vertice
var morphVerticeHolder = [];
for(var i = 0; i < 20; i++) {
morphVerticeHolder[i] = [];
}

这是我沿轴插入顶点的代码。请注意,我也同时插入​​我的变形顶点。 mI代表网格间隔。

for(var i = xstart; i <= xend; i+= mI) {
geo.vertices.push(new THREE.Vector3(i,0,0));
for(var j = 0; j < 20; j++) { //20 Frames of the morph animation
morphVerticeHolder[j].push(new THREE.Vector3(i,0,0));
}
}

此代码推送所有顶点。 i 沿 x 轴排列,而 j 沿 theta 排列,填充网格的顶点。

//Push the vertices
var tmesh = 2*Math.PI/meshPoints; //Theta mesh interval
verticeCounter = 0;
for(var i = xstart; i <= xend; i+=mI) {
var rMain = solveEquation(i);
var rSecond = solveEquation(i+mI);
var counter = 0;
for(var j = 0; j < 2*Math.PI; j += tmesh) {
geo.vertices.push(new THREE.Vector3(i, rMain*Math.cos(j/1000),rMain*Math.sin(j/1000)));
for(var k = 0; k < 20; k++) {
morphVerticeHolder[k].push(new THREE.Vector3(i, rMain*Math.cos(j*(k+1)/20),rMain*Math.sin(j*(k+1)/20)));
}
}
}

除以 1000 的目的是使原始网格体开始接近 0,然后使用变形顶点(范围从所需值的 1/20 到 20/20)对其进行旋转动画。

然后我推这些脸。您可以尝试解释我的算法,但本质上我想出了如何跟踪哪个顶点在哪里。

for(var i = 0; i < meshPoints; i++) {
var sI = meshPoints*(i+1);
var sI2 = meshPoints*(i+2);
for(var j = 0; j < meshPoints-1; j ++) {
if(i === 0) {
//First Point, Fill end
geo.faces.push(new THREE.Face3(sI+j, sI+j+1, 0));
geo.faces.push(new THREE.Face3(sI+j+1, sI+j, 0));
//Filll Body
geo.faces.push(new THREE.Face3(sI+j, sI+j+1, sI2+j));
geo.faces.push(new THREE.Face3(sI+j+1, sI+j, sI2+j));
geo.faces.push(new THREE.Face3(sI+j+1, sI2+j, sI2+j+1));
geo.faces.push(new THREE.Face3(sI2+j, sI+j+1, sI2+j+1));
} else if(i === meshPoints-1) {
//Last Point, Fill end
geo.faces.push(new THREE.Face3(sI+j, sI+j+1, meshPoints-1));
geo.faces.push(new THREE.Face3(sI+j+1, sI+j, meshPoints-1));
} else {
geo.faces.push(new THREE.Face3(sI+j, sI+j+1, sI2+j));
geo.faces.push(new THREE.Face3(sI+j+1, sI+j, sI2+j));
geo.faces.push(new THREE.Face3(sI+j+1, sI2+j, sI2+j+1));
geo.faces.push(new THREE.Face3(sI2+j, sI+j+1, sI2+j+1));
}
}
}

剩下的就是初始化等等。

for(var k = 0; k < 20; k++) {
geo.morphTargets.push( { name: "target" + k, vertices: morphVerticeHolder[k]} );
}

var uniforms = {
resolution: { type: "v2", value: new THREE.Vector2 },
zmax: { type: "f", value: maxz},
zmin: { type: "f", value: minz}
};
var mat = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: document.getElementById('cubeVertexShader').innerHTML,
fragmentShader: document.getElementById('cubeFragmentShader').innerHTML
});
functionObject = new THREE.Mesh( geo, mat);
this.scene.add(functionObject);
functionObject.name = 'current';

this.animation = new THREE.MorphAnimation( functionObject, 'Revolution' );
this.animation.play();

this.setWithinRender(function() {
this.animation.update(.1);
});

this.setWitinRender 将匿名函数放入 THREE.js 的渲染循环中(这是一个与 THREE 的设置分开调用的函数。

正如我上面提到的,网格会渲染,如果我在插入原始顶点时去掉/1000,我会得到整个表面。但是,按上述设置的动画无法播放。有人对此有任何见解吗?

谢谢!

最佳答案

经过更多研究并深入研究源代码,我发现所使用的 Material 必须将 morphTargets 属性设置为 true。我已经用我正在使用的着色器 Material 尝试过此操作,但是您必须在顶点着色器中手动应用 morphTargetInfluences。

因此,我将 Material 切换到

var mat = new THREE.MeshNormalMaterial( { color: 0x990000, morphTargets: true } );

一切都很顺利!

关于javascript - THREE.js 中自定义网格的变形目标动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26662503/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com