3DでのPHPのパーティクルシステム

子供の頃から、物理エンジンを書くという大切なプログラミングの夢があります。 夢にふさわしいので、私は決してそれに近づきませんでした。 しかし、屋内で勤務しなければならなかったとき、2、3泊があり、ラップトップを持っていました。

一般的に、PHPでパーティクルの動きと衝突をシミュレートすることを約束しました。 なぜPHPで? これは、プログラミングの考えを自由に表現できる唯一の言語だからです。 一般的に、最初に座標がコンソールに表示され、次にグラフィック写真を撮り始めました。 すぐにアニメーションを生成するという考えが生まれました...

画像





グーグルで、映画のフレームを収集できる古代のクラスGIFEncoder v.2を見つけました! 私はとても励まされ、実験を続けました。

最初の、複雑で主な問題は、パルスの追加でした。 実際には、X上のパーティクルの単純な移動(たとえば1)と同じYで、360面すべてに散在するパーティクルは円を形成することを望みませんでした-頑固に菱形に並んでいます。 私は代数をうまく教えませんでしたが、係数を試して即興することに興味がありました。

2番目の問題は、平面上の3Dポイントに散在する投影です。 幾何学を代数以上に教えなかったので、私は即興の係数によって助けられました。正しい係数では、多かれ少なかれ妥当な投影法を選択することは容易ではありません。 何らかの方法で、上記のビデオを生成するスクリプトを作成するのに熱意は十分でした。 また、メカニズムはコードで直接説明するのが最適です。 PHPを自由に読んで理解する必要があります。

<?php //    ,      =) set_time_limit(0); //   $start = microtime(1); // GIFEncoder  : // http://saintist.ru/2009/05/12/316/ include('gif_animate.php'); //     class space { //   public $points = array(); //   -  //       private $x; private $y; private $z; // . .  step. public $steps = 0; public function __construct($x, $y, $z) { $this -> x = $x; $this -> y = $y; $this -> z = $z; } // -  ... public function addPoint($point, $x, $y, $z, $fx = 0, $fy = 0, $fz = 0) { array_push($this -> points, array($point, $x, $y, $z)); $point -> addP($fx, $fy, $fz); } // .  ,     . //  -  ,    . //   (  -   )     , //    . ,    =    // ,     < 1. // , 1  =     1  1   . //       . public function step() { //      $t = 1; //   . //    ,   . $busy = array(); //     space       //     foreach ($this -> points as $n => &$point) { $x = $point[1]; $y = $point[2]; $z = $point[3]; //      -  ,    if (!($x >= 0 && $x < $this->x && $y >= 0 && $y < $this->y && $z >= 0 && $z < $this->z)) { unset($this->points[$n]); continue; } //       $f = abs($point[0]->p['fx']) + abs($point[0]->p['fy']) + abs($point[0]->p['fz']); //    ,     1   $t if ($f > 0 && 1 / $f < $t) { //      $t = 1 / $f; } } //  .  . foreach ($this -> points as $n => &$point) { $xyz = abs($point[0]->p['fx']) + abs($point[0]->p['fy']) + abs($point[0]->p['fz']); //        $hypo = pow(abs($point[0]->p['fx']), 2) + pow(abs($point[0]->p['fy']), 2) + pow(abs($point[0]->p['fz']), 2); //   $move_x -  ,      . //   . //    X  Y  ,  Z -    //     X  Y, . if ($point[0]->p['fx'] != 0 && $xyz > 0) { if ($point[0]->p['fx'] < 0) { $fxmin = 1; } $move_x = sqrt($hypo) * ($point[0]->p['fx'] / $xyz); if (isset($fxmin)) $move_x = $move_x * -1; } else { $move_x = 0; } if ($point[0]->p['fy'] != 0 && $xyz > 0) { if ($point[0]->p['fy'] < 0) { $fymin = 1; } $move_y = sqrt($hypo) * ($point[0]->p['fy'] / $xyz); if (isset($fymin)) $move_y = $move_y * -1; } else { $move_y = 0; } if ($point[0]->p['fz'] != 0 && $xyz > 0) { if ($point[0]->p['fz'] < 0) { $fzmin = 1; } $move_z = sqrt($hypo) * ($point[0]->p['fz'] / $xyz); if (isset($fzmin)) $move_z = $move_z * -1; } else { $move_z = 0; } //        $point[1] += $move_x*$t; $point[2] += $move_y*$t; $point[3] += $move_z*$t; } $this -> steps+=$t; } //    space  GIF public function shot() { $r = imagecreatetruecolor($this -> x+1, $this -> y+1); // ,   foreach ($this -> points as &$point) { $x = $point[1]; $y = $point[2]; $z = $point[3]; if ($x >= 0 && $x < $this->x && $y >= 0 && $y < $this->y && $z >= 0 && $z < $this -> z) { // ,  .  ,  ,    Z //   ,     -  Z. $ox = $this->x / 2; $oy = $this->y / 2; $oz = $this->z / 2; $xf = $x - $ox; $yf = $y - $oy; $zf = $z; $xr = $x - $xf / ($this->z/($this->z - $z)); $yr = $y - $yf / ($this->z/($this->z - $z)); imageline($r, $xr, $yr, $xr, $yr, $point[0]->color); } } ob_start(); imagegif($r); return ob_get_clean(); } } class Point { public $p = array('fx' => 0, 'fy' => 0, 'fz' => 0); public $color; //     public function __construct() { $red = dechex(rand(1, 255)); if (strlen($red) < 2) $red = '0'.$red; $green = dechex(rand(1, 255)); if (strlen($green) < 2) $green = '0'.$green; $blue = dechex(rand(1, 255)); if (strlen($blue) < 2) $blue = '0'.$blue; $this->color = hexdec("0x$red$green$blue"); } public function addP($fx = 0, $fy = 0, $fz = 0) { $this->p['fx'] += $fx; $this->p['fy'] += $fy; $this->p['fz'] += $fz; } } $gifs = array(); // GD- GIF-,     $space = new space(399, 399, 399, false, true); //     . //      ,     $rands = range(-10, 10, 0.5); for ($i=0; $i<1000; $i++) { // ...    $space->addPoint(new Point, 200, 200, 200, $rands[array_rand($rands)], $rands[array_rand($rands)], $rands[array_rand($rands)]); } //   100      ... while($space->steps < 100) { $nshot = $space -> steps; $space -> step(); if ((int)$nshot < (int)$space -> steps) { array_push($gifs, $space -> shot()); echo 'Step #',$space -> steps,"\r\n"; } } //    ... $gif = new GIFEncoder($gifs, 0, 0, 0, 0, 0, 0, 'bin'); file_put_contents('c:\anim.gif', $gif -> GetAnimation()); echo "\r\nTime: ",substr(microtime(1) - $start, 0, 4); //   :-)
      
      





原則はあなたに明らかです。 最初のビデオの1つはこれでした:

画像

次に、3Dで次のようにします。

画像

でたらめ? おそらく。 しかし、最もクレイジーなアイデアを実装することを恐れないでください。 これは、プログラミング言語で考える方法を学ぶための最良の方法です。



All Articles