數碼資源網

文章頻道 軟件下載 安卓下載 蘋果下載

當前位置:首頁文章中心動畫專欄Maya → 用particle的instancer模擬爆破牆效果

用particle的instancer模擬爆破牆效果

時間:2005-10-29 23:15:30人氣:191作者:網友整理
Particle Flow安卓版(粒子流動態壁紙) v1.4 最新版
Particle Flow安卓版(粒子流動態壁紙) v1.4 最新版 for Android
  • 類型:安卓桌麵美化大小:13.21M語言:簡體中文 評分:3.0
  • 手機上都會帶有壁紙,而好看的壁紙還是要下載的,ParticleFlow安卓版是一...
立即下載
爆破模擬最新版(惡趣味模擬遊戲) v1.1.2 安卓版
爆破模擬最新版(惡趣味模擬遊戲) v1.1.2 安卓版 for Android
  • 類型:休閑益智大小:47.64M語言:簡體中文 評分:3.0
  • 想要體驗爆炸的快感,你就來惡趣味模擬遊戲爆破模擬最新版就能體驗到,這款遊戲中,玩...
立即下載
爆破物理模擬器手機版v0.9.8 安卓版
爆破物理模擬器手機版v0.9.8 安卓版 for Android
  • 類型:飛行射擊大小:35M語言:簡體中文 評分:3.0
  • 在你心情不好的時候,可以來玩玩爆破物理模擬器手機版哦,是非常逼真的再現了物品被爆...
立即下載
 初始化位置
   首先打開2_1_instance_brickwall_base.mb文件,在這個文件裏可以由一組磚組成的一麵牆。這麵牆是由一些磚塊組成,稍後我們將用一些破磚代替它們,來讓我們看看這個場景是怎麼樣設置的.

   設置如圖。

 1、所有的磚都需要freeze transform。
   2、我們需要建粒子去發射它。可以運行這個命令://create particle node particle -n wall_front_PTL;
   3、創建一個屬性,當開始播放場景的時候我們將用這個屬性旋轉磚塊。打開粒子的屬性欄,增加一個per-particle的屬性,名稱為rotationPP。
   4、粒子將從每一塊磚的位置發射。我們首先從所有的節點中捕獲一個列表,然後循環每一個節點,用emit命令從每個節點的位置發射粒子。老外用了這樣一段腳本來完成這個操作。emit_brick_particles.mel:// 獲取前牆磚的名稱列表string $nodeList[] = `ls -dag -type transform "o_frontWall_LOC|*PLY" "i_frontWall_LOC|*PLY" "side_frontWall_LOC|*PLY"`;
// 用循環語句讓每一塊磚發射一個粒子for( $node in $nodeList ) {  // 得到每一塊磚的位置  float $pos[] = `xform -q -ws -t $node`;  // 確定每一塊磚的大致體積  // 當我們破碎磚塊的時候就會用到:
   float $bb[] = `xform -q -ws -bb $node`;
   float $x = abs( $bb[3] - $bb[0] );
   float $y = abs( $bb[4] - $bb[1] );
   float $z = abs( $bb[5] - $bb[2] );
   vector $v = <<$x, $y, $z>>;
   // 得到磚的長度 float $vol = mag( $v );  
   //發射一個粒子  emit -o wall_front_PTL
   -pos $pos[0] $pos[1] $pos[2]
   -at mass -fv $vol;
   } // for $node in $nodeList
   // 將此時的粒子保存為初始狀態
   saveInitialState wall_front_PTL;
   emit_brick_particles.mel (1.08k)

[page]

 5.記錄粒子產生的次序。因為磚和粒子之間沒有真正的關聯,我們不得不依靠maya的物體列表清單。按字母順序獲取$nodelist變量裏的列表,這是非常重要的一點,這將幫助我們正確的對磚塊進行instance。
   6.我們現在為每個粒子建立instance.我們將像前麵發射粒子一樣定義這個列表。
   //選擇磚塊
   select -r `ls -dag -type transform "o_frontWall_LOC|*PLY" "i_frontWall_LOC|*PLY"
   "side_frontWall_LOC|*PLY"`;
   7.選擇菜單particles>instancer(Replacement)>optionBox.在instanced objects列表裏,你將會看到你所選擇的按字母順序排列的所有磚塊。單擊create 按鈕,你會看到instance物體已經出現了。
   你會注意到有些磚的位置不正確。當你使用默認值創建instance時,instance會使用列表中的第一個物體。我們將指定instance使每個粒子使用它相同位置的磚。因為在前麵我們已經正確的設置了我們的粒子和instance,所以現在就可以簡單的將粒子的ID作為磚的列表索引。
   8.選擇粒子wall_front_PTL打開屬性編輯器找到instancer一欄。
   9.打開objectindex下拉菜單,設置為particleID,我們將看到磚塊已經恢複到了正確的位置。
   10.先添加一個per-particle屬性,名稱為rotationPP,打開rotation下拉菜單,設置為rotationPP。
   當這些磚移動的時候,我們將用這個屬性使磚產生翻滾的效果。

   開始模擬
   有趣的事馬上就要發生了,我們會從內部炸毀這麵牆。我們遇到的第一個問題是重力,怎樣使磚塊受到重力影響呢,在它們被推出去之前不讓它們發生移動。有許多方法:
味  1)在粒子的runtime expression裏創建一個重力,當粒子的速度不為零的時候它將受到重力影響,如果粒子已經接觸到了地麵,將它所受的重力設置為0。
   //獲取位置
   vector $pos=position;
   //如果粒子已經移動,並且沒有掉到地麵上,受重力影響。
   if(mag(velocity)>0&&$pos.y>0.01)
   velocity+=<<0,-32.17,0>>;
   2)創建一個真正的重力場,將它的volume shape設置為cube。將它的位置放在牆的前麵,當粒子被推出去以後它就會受到重力的影響。
   第二種方法比較實用,如果你的場景物體不是很規則,那可能需要建立很多個重力場,並確保他們互相不交迭。

[page]

 現在我們打開2_2_instance_brickwall_sim_base.mb,前麵磚牆已經設置好了instance,一些場和碰撞物體將在適當的時間將磚牆碰出去。如果現在播放,會看到磚被推了出去掉在了地上。這是因為有許多的場和碰撞物體來模擬這個爆炸動畫。可以看到在磚飛出去的時候並沒有旋轉,現在我們來加這個效果,讓磚旋轉著飛出去。
   我們將根據一些因素來旋轉這些磚:
   a.磚的速度。
   b.磚的質量(大的磚相對重一些,因此它們轉的會慢一些)。
   c.上麵的磚朝一個方向旋轉,下麵的磚會朝另一個方向旋轉,距離爆炸中心的會旋轉的快一些。
   d.用一個隨機數值去乘以旋轉值,讓它們的速度有些變化。
   現在我們要為粒子增加一些屬性。因為我們是使用emit命令來發射的粒子,所以它們的創建表達式將被忽略。我發現可以在運行表達式中創建一個“假的”創建表達式。這個創建表達式將出現在第二幀,是在爆炸前運行。
   我們也可以用epicentre_LOC這個locator的位置來決定爆炸什麼時候發生。
   1.首先,我們給wall_front_PTL的粒子增加幾個per-particle的屬性。3個per-particle float屬性的,名稱為rotXPP,rotYPP和rotZPP,1個per-particle float屬性的,名稱為magVelPP。
   2.接下來,我們創建這個“假的”創建表達式。它將運行在模擬之前,在runtime expression中輸入下列表達式:
   //假的創建表達式if(frame==`playbackOptions -q -min`+1){
   //獲取位置
   vector $pos = position;
   //獲取質量,並且取它的倒數
   float $mass=1/(mass);
   //獲取爆炸中心的位置
   float $epicentreF[]=`xform -q -ws -t epicentre_LOC`;
   vector $epicentre=<<$epicentreF[0],$epicentreF[1],$epicentreF[2]>>;
   //確定粒子和爆炸中心的距離
   float $distToCentre=mag($pos-$epicentre);
   //定義旋轉值
   float $rx=deg_to_rad(deg_to_rad(rand(-10)));
   float $ry=deg_to_rad(deg_to_rad(rand(5)));
   float $rz=deg_to_rad(deg_to_rad(rand(2)));
   //根據粒子與爆炸中心的關係修改旋轉值
   if($pos.y<$epicentre.y)$rx*=-1;
   if($pos.x<$epicentre.x)$ry*=-1;
   //根據粒子與爆炸中心的距離關係修改旋轉速度
   float $distNorm=1-smoothstep(0,10,$distToCentre);
   //最後為粒子指定旋轉值
   rotXPP=$rx*$distNorm*$mass;
   rotXPP=$ry*$distNorm*$mass;
   rotXPP=$rz*$distNorm*$mass;
   }//假的創建表達式結束
   3.現在我們繼續給增加運行表達式
   //獲取旋轉值
   vector $rot=rotationPP;
   //獲取速度
   //確保當粒子沒有移動的時候不旋轉。
   magVelPP=smoothstep(1,30,mag(velocity));
   //加上現有的旋轉值
   float $rx=$rot.x+rotXPP*magVelPP;
   float $ry=$rot.y+rotYPP*magVelPP;
   float $rz=$rot.z+rotZPP*magVelPP;
   //指定給旋轉值
   rotationPP=<<$rx,$ry,$rz>>;
   在粒子的屬性中找到instance欄,將rotation改成rotationPP現在重新播放,可以看到磚塊旋轉著飛出去了。

[page]

下麵我們來做磚塊被炸碎的效果
   首先打開2_3_instance_brickwall_broken_base.mb文件,打開outline可以看到,我們已經準備好了,20種破碎成不同形態的磚,每塊磚都把它碎成了幾塊。

   每個碎塊的軸心點都在它的中心。並不在世界坐標的中心,如果讓這些碎塊的軸心都處於世界坐標的中心,可能設置起來會容易一些,可是在我們這個效果中旋轉起來會出現問題。這就是為什麼讓他們的軸心點都處在自身中心的原因。

[page]

 我給大家提供一個腳本,它能使這些碎磚instance好的磚塊:emit_brick_chunks.mel
   1.首先我們選擇所有的碎塊,我們使用我已經提供的一個腳本assign_brick_ids.mel,在命令行輸入
source assign_brick_ids.mel;assign_brick_ids();
   assign_brick_ids.mel (0.64k)
   2.接下來,我們選擇一個磚測量它與爆炸中心的距離。靠近爆炸中心的將會被炸成小碎片。如果你注意觀察了,你就會發現名稱代號小的是碎塊多的磚,名稱代號大的是碎塊少的磚。我們將在距離爆炸中心近的地方用一些碎塊多的磚,遠的地方用一些碎塊少的磚。實現這個效果的所有代碼都在emit_brick_chunks.mel。
   emit_brick_chunks.mel (4.3k)
   global proc emit_brick_chunks() {
    // all nodes under which bricks sit
    string $nodeList[] = { "o_frontWall_LOC", "i_frontWall_LOC", "side_frontWall_LOC" };
    // 初始化變量
    vector $epicentre = f2v( `xform -q -ws -t epicentre_LOC` );
    string $brickName = "brokenBrick";
    // 循環便曆所有節點
    for( $node in $nodeList ) {
    // 顯示出狀態
    print( "// WORKING on group "+$node+"...\n" );
    // 列出所有的子項
    string $children[] = `listRelatives -c -type transform $node`;
    //為朝向旁邊的磚進行一個不同的設置.
    // 可以在 'brokenBricksR_LOC'下找到
    if( $node == "side_frontWall_LOC" )
    $brickName = "brokenBrickR";
    // 循環遍曆每一塊磚
    for( $brick in $children ) {
     // 確定距離
    vector $brickPos = f2v( `xform -q -ws -t $brick` );
    float $dist = mag( $brickPos - $epicentre );
   // 選擇一塊磚
   // 我們需要選擇一塊磚. 有20塊。
   // 根據距爆炸中心的距離
   // 按大塊和小塊分布
        float $minDist = 1.4;
        float $maxDist = 9.1;
        float $diffDist = $maxDist - $minDist;
        // determine normalized distance
        float $normDist = linstep( $minDist, $maxDist, $dist );
        float $weight = $dist / $diffDist;
        float $gauss = gauss( $weight );
        $gauss = abs( $gauss ) * 20;
        $gauss = int( $gauss );
        $gauss = clamp( 1, 20, $gauss );
        // $brickIndex 是實際已經選擇的磚
        int $brickIndex = $gauss;
   // 在每個碎塊的中心發射粒子 
        //列出所有的碎塊
        string $chunks[] = `listRelatives -c -type transform ($brickName+$brickIndex+"_LOC")`;
        // 得到磚塊的世界坐標位置
        vector $brickPos = f2v( `xform -q -ws -t $brick` );
        // 設置發射器
        string $emitStr = "emit -object wall_front_PTL ";
        // 在每個碎塊上建一個發射器
        for ($chunk in $chunks) {
        // 得到每一個碎塊的index號 -- 我們用這個設置粒子的objectIndexPP          
        int $chunkIndex = `getAttr ($chunk+".index")`;
        // 得到每一個碎塊的世界坐標位置. 
        vector $chunkPos = f2v( `xform -q -ws -t $chunk` );
         // 碎塊的位置加上磚的位置
          $chunkPos += $brickPos;
          // 確定每一個碎塊的體積用'bb_calculateBB'
          float $vol = `bb_calculateBB( $chunk )`;
          // 連接 $emitStr
          $emitStr += "-pos "+$chunkPos.x+" "+$chunkPos.y+" "+$chunkPos.z+" ";
          $emitStr += "-at initPosPP -vv "+$chunkPos.x+" "+$chunkPos.y+" "+$chunkPos.z+" ";
          $emitStr += "-at scalePP -vv 1 1 1 ";
          $emitStr += "-at rotationPP -vv 0 0 0 ";
          $emitStr += "-at initMassPP -fv "+$vol+" ";
          $emitStr += "-at mass -fv "+$vol+" ";
          $emitStr += "-at objectIndexPP -fv "+$chunkIndex+" ";
          $emitStr += "-at visibilityPP -fv 1 ";
         } // for chunk in chunks
         //在每一塊上執行發射命令
         eval($emitStr);
      } // for brick
    } // for node
    // 將粒子保存為初始狀態
   saveInitialState wall_front_PTL;
   // 顯示狀態
   print("// DONE emitting chunks.\n");
   } // emit_brick_chunks

 

[page]

3.上麵的操作讓我們為每一個碎塊的位置都放置了一個粒子。
   4.然後我們對粒子進行instance,可以用objectIndexPP來做這個,首先選擇磚塊。select -r `ls -tr,rokenBrick*_*PLY"`。
   5.particle>instancer>optionbox如下設置:
   scale 設置為scalePP
   visibility 設置為visibilityPP
   objectIndex 設置為objectindexPP
   rotation 設置為rotationPP
   單擊create 如果沒有做錯的話就已經好了,重新播放。

 

感謝速聯科技、八度網絡、九九數據、億恩科技、群英網絡讚助部分帶寬!

關於本站 | 聯係方式 | 版權聲明 | 下載幫助(?) | 網站地圖

Copyright 2002-2020 95262.com 【數碼資源網】 版權所有 粵ICP備2020128507號-1

本站所有軟件來自互聯網,版權歸原著所有。如有侵權,敬請來信告知 ,我們將及時撤銷。