2017-07-11 21 views
1

(x、y、z)を(x、y)に変換するために必要な数学を見つけるために、PHPでボックスを作成できます。すべての点がグリッド上にあり、回転はありません。3Dオブジェクトを2D空間に変換する

私は私が道の一部を取得します。このソリューションhttps://stackoverflow.com/a/25955134/379249を試してみましたが、私はポリゴン例えば

のポイントを把握する必要があり、私は以下の赤で示した大きな箱を持っています。

boxes

私はそれをいずれかの幅、長さ、高さの寸法および出発点を与えることができるようにする必要があるか、私はそれを各面を構成するすべての4つのポイントを与えることができます。

私はそれが3Dに見えるようにするためにそれらを翻訳する必要があります。これは私が上に乗ったものです。

一度、赤いボックスが作成されたら、緑色、青色、またはオレンジ色の同じ機能を使用して他のボックスを作成する必要があります。

私はコードを作成できますが、私は翻訳を行うために数学に固執しています。

アイデア?

ありがとうございます! @へ

EDIT **

おかげで私はそれが非常に近い取得することができていますuser2464424。以下は私のコードです。

と私の生成された画像。

<?php 
function RotatePoint($sin,$cos,$x,$y) { 
    return array($x*$cos - $y*$sin, $y*$cos + $x*$sin); 
} 

$im = imagecreatetruecolor(200, 200); 

$white = imagecolorallocate($im, 255, 255, 255); 
imagefilledrectangle($im, 0, 0, 200, 200, $white); 

$brown = imagecolorallocate($im, 120, 53, 31); 
$green = imagecolorallocate($im, 23, 255, 65); 
$blue = imagecolorallocate($im, 31, 23, 255); 
$orange = imagecolorallocate($im, 255, 185, 23); 

function draw_box(&$image, $color, $start, $width, $length, $height) 
{ 
    $camx = 80; 
    $camy = 240; 
    $camz = 40; 

    $yaw = 10; 
    $pitch = 20; 
    $sy = sin(-$yaw); $cy = cos(-$yaw); $sp = sin(-$pitch); $cp = cos(-$pitch); 

    $start_x = $start[0]; 
    $start_y = $start[1]; 
    $start_z = $start[2]; 

    // Draw 6 faces 
    for ($i = 0; $i < 6; $i++) 
    { 
     switch ($i) 
     { 
      case 0: 
       $face = array(
        array($start_x, $start_y, $start_z), 
        array($start_x+$width, $start_y, $start_z), 
        array($start_x+$width, $start_y, $start_z+$height), 
        array($start_x, $start_y, $start_z+$height) 
       ); 
       break; 
      case 1: 
       $face = array(
        array($start_x, $start_y+$length, $start_z), 
        array($start_x+$width, $start_y+$length, $start_z), 
        array($start_x+$width, $start_y+$length, $start_z+$height), 
        array($start_x, $start_y+$length, $start_z+$height) 
       ); 
       break; 
      case 2: 
       $face = array(
        array($start_x, $start_y, $start_z), 
        array($start_x, $start_y+$length, $start_z), 
        array($start_x, $start_y+$length, $start_z+$height), 
        array($start_x, $start_y, $start_z+$height) 
       ); 
       break; 
      case 3: 
       $face = array(
        array($start_x+$width, $start_y, $start_z), 
        array($start_x+$width, $start_y+$length, $start_z), 
        array($start_x+$width, $start_y+$length, $start_z+$height), 
        array($start_x+$width, $start_y, $start_z+$height) 
       ); 
       break; 
      case 4: 
       $face = array(
        array($start_x, $start_y, $start_z+$height), 
        array($start_x+$width, $start_y, $start_z+$height), 
        array($start_x+$width, $start_y+$length, $start_z+$height), 
        array($start_x, $start_y+$length, $start_z+$height) 
       ); 
       break; 
      case 5: 
       $face = array(
        array($start_x, $start_y, $start_z), 
        array($start_x+$width, $start_y, $start_z), 
        array($start_x+$width, $start_y+$length, $start_z), 
        array($start_x, $start_y+$length, $start_z) 
       ); 
       break; 
     } 


     $polygon = array(); 
     foreach ($face as $point) 
     { 
      $x = $point[0] - $camx; 
      $y = $point[1] - $camy; 
      $z = $point[2] - $camz; 

      $rot = RotatePoint($sy,$cy,$x,$y); 
      $x = $rot[0]; 
      $y = $rot[1]; 

      $rot = RotatePoint($sp,$cp,$z,$y); 
      $z = $rot[0]; 
      $y = $rot[1]; 

      $polygon[] = $x; 
      $polygon[] = $z; 
     } 

     imagepolygon($image, $polygon, 4, $color); 
    } 
} 

draw_box($im, $brown, array(0, 0, 0), 80, 80, 80); 

draw_box($im, $green, array(0, 0, 0), 40, 40, 40); 

draw_box($im, $blue, array(0, 0, 40), 30, 20, 10); 

draw_box($im, $orange, array(60, 0, 0), 15, 40, 80); 

imagepng($im, './image.png'); 

imagedestroy($im); 
?> 
<img src="image.png"> 

enter image description here

夫婦の問題。

1:軸の原点を下に表示するにはどうすればいいですか?右は逆さまです。

2:私はいつも400x400の画像で制作したいと考えていますが、それがオフにならないようにするにはどうすればいいですか?

3:コンテナが40x40x40または10x100x100の場合、原点を調整して画像の下部に常に表示し、ボックスのサイズが適切になるように調整するにはどうすればよいですか? https://gist.github.com/rzfarrell/3a9e5046dcfd6bd2d2f4bfa1a34b21ef

この行います:ここ

**

EDITは、最終的なコードにリンクされて

enter image description here
+1

私はあなたが達成しようとしているのは正射投影です、それは正しいですか? – user2464424

+2

2Dに3Dを投影する方法が* bazillions *あります。 alreadymがない場合は、https://en.wikipedia.org/wiki/Graphical_projectionをご覧ください。また、翻訳は簡単です(x '= x + deltaなど)。ローテーションははるかに難しいです:https://en.wikipedia.org/wiki/Rotation_(mathematics) –

+0

@ user2464424はい正射投影は私が探しているものです。 – bones

答えて

1

に対する3D点の正射影の主なアイデア3D空間内の自由なカメラは、a)原点を中心とし、b)回転しないようにカメラを移動させて回転させることである。キャッチすることは、3D世界を構成するすべての点が、変形されるにつれてカメラを堅く追いかける必要があるということです。次いで

$x = $pointx - $camx; $y = $pointy - $camy; $z = $pointz - $camz; 

2)の周りに点を回転させる:

これは通常、2段階のプロセスに集約:

1)まず、反転原点カメラベクトルによってポイントを翻訳カメラのピッチ角とヨー角による原点を無効にします(おそらくラジアン単位)。

$sy = sin(-$yaw); $cy = cos(-$yaw); $sp = sin(-$pitch); $cp = cos(-$pitch); 

function RotatePoint($sin,$cos,$x,$y) { 
    return array($x*$cos - $y*$sin, $y*$cos + $x*$sin); 
} 

$rot = RotatePoint($sy,$cy,$x,$y); 
$x = $rot[0]; 
$y = $rot[1]; 

$rot = RotatePoint($sp,$cp,$z,$y); 
$z = $rot[0]; 
$y = $rot[1]; 

これで完了です。ここで、$x$zは、カメラの中心からのカメラ面内の2D点の座標を表し、$yは、カメラ面との点の垂直距離です。

画像を出力したい場合は、画像サイズに合わせて座標を制限して制限することができます(これは簡単です)。あなたが考慮する必要がある1つのことは、彼らがカメラの後ろにいることを意味するので、y<=0を持つすべての点を無視することです。

+0

ありがとう!私はいくつかの作業コードを取得し、それを使って私の質問を更新しましたが、まだ解決するためのいくつかの問題があります。 – bones

+1

@bonesあなたは歓迎ですが、もっと注意を払うと、いくつかの部分に混乱があります。まず、カメラの向き角度はラジアンであると想定されます。変換を行うには、['' deg2rad'](http://php.net/manual/en/function.deg2rad.php)関数を使用します。次に、ポイントの座標が変換されたら、それらのポイントの座標を変換することができます。たとえば、 '$ z'を否定して、結果を上下逆にすることができます。また、 'screen'は左上隅に(0,0)を持つイメージなので、 '= $ CanvasHalfWidth + $ x;'や '= $ CanvasHalfHeight- $ z;'のようなオフセットを追加したい場合は – user2464424

+1

@骨を拡大縮小するには、 '$ x'と' $ z'にズームと呼ばれるいくつかの要素を乗算することもできます。修正を行ったら、カメラ位置(-25、-50,100)、ヨー= deg2rad(-35)、ピッチ= deg2rad(35)を試してください。私はこれらのパラメータを試してみて、多かれ少なかれ中心のイメージを得ました。 – user2464424

関連する問題