2017-07-11 197 views
1

我正在尝试查找将(x,y,z)转换为(x,y)所需的数学运算,以便可以使用php创建框。所有点将在网格上,并且没有旋转。将3D对象转换为2D空间

我已经尝试了这种解决方案https://stackoverflow.com/a/25955134/379249这让我的存在方式的一部分,但我需要弄清楚的多边形

。例如点,我在下面红色显示一个大箱子。

boxes

我需要能够给它要么宽度,长度,高度的尺寸和起点或我可以给它的所有四个点构成每个面上。

我需要翻译那些使它看起来3D,这是我绊倒了。

一旦红色框被创建,我也需要能够使用相同的功能,如绿色,蓝色或橙色创建其他框。

我可以创建代码,但我坚持数学来做翻译。

任何想法?

谢谢!

编辑 **

感谢@ 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

,使此: enter image description here

+1

我认为你想要实现的是正射投影,这是正确的吗? – user2464424

+2

有* bazillions *的方式投影3D到2D。如果您还没有,请查看:https://en.wikipedia.org/wiki/Graphical_projection。此外,翻译很容易(只需做x'= x + delta等)。轮换更难:https://en.wikipedia.org/wiki/Rotation_(mathematics) –

+0

@ user2464424是正射投影是我正在寻找。 – bones

回答

1

对一个三维点的正投影的主要思想3D空间中的免费摄像头是移动和旋转摄像头,使其最终以a)为中心,b)不旋转。值得一提的是,组成3D世界的所有要点必须严格按照相机进行转换。

这通常归结为一个两步过程:

1)首先,通过反相原点相机向量平移该点:然后

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

2),围绕所述旋转点由相机的俯仰角和偏航角取反(可能以弧度表示):

$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是该点与相机平面的垂直距离。

如果您想要输出图片,您可能需要缩放和限制坐标以适应图像大小,这很平凡。你必须考虑的一件事是忽略所有具有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