2014-10-30 114 views
0

我正在創建一個動畫,該動畫顯示關於創建3D曲面的2D功能的旋轉。我已經能夠成功渲染表面,現在我正在嘗試使用MorphTargets創建動畫部分。在THREE.js中爲自定義網格變形目標動畫

不幸的是,雖然我已經成功地將所有的變形框架推送到了我的幾何體中,但我無法使動畫播放。我發現的所有動畫示例都使用攪拌器導入模型,因此不是完全有用(許多也是過時的)。

我正在看變形馬作爲例子(http://threejs.org/examples/#webgl_morphtargets_horse),並試圖儘可能複製代碼,但我沒有成功。

這裏是我的代碼初始化morphVerticeHolder,這是一個二維數組來保存每個動畫幀

//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)); 
    } 
} 

該代碼推動所有的頂點。我沿着x軸範圍,而j沿着θ範圍,填充網格的頂點。

//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,然後動畫它旋轉使用變形的頂點(其範圍從所希望的值,以20/20的1/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,我會得到整個曲面。但是,如上所述設置的動畫不起作用。有沒有人對此有所瞭解?

謝謝!

回答

3

經過多一點研究並深入研究源代碼後,我發現所使用的材質必須將morphTargets屬性設置爲true。我曾嘗試使用我正在使用的着色器材質,但是必須在頂點着色器中手動應用morphTargetInfluences。

因此,我換了材料到

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

和一切工作正常!