간단한 큐브 그리기 실제 3 차원 큐브를 그리는 것에 대한

우리는 실제 3 차원 큐브를 그리는 것에 대한 단일 도전이 없으므로 여기에갑니다.

도전

당신의 임무는 원근감으로 회전 큐브를 그리는 것입니다. 별도의 창에 있거나 이미지로있을 수 있습니다.

입력

입력은 0에서 359.99 사이의 3 개의 개별 숫자입니다. 이는 x, y 및 z 축을 중심으로 한 회전 각도를 나타냅니다.

0 0 0
30 0 40
95 320 12

산출

별도의 창에 표시하거나 이미지를 저장할 수 있습니다. 모든 유형의 디스플레이 (벡터 기반, 래스터 화 된 등)를 사용할 수 있습니다.

편집 : 텍스트 출력 만있는 골프 언어를 허용하기 위해 ASCII도 허용됩니다.

래스터 화 된 그래픽 또는 ASCII 그래픽의 출력은 50 * 50 이상이어야합니다 (래스터 화 픽셀, ASCII 문자)

추가 정보

양의 z 축은 창을 가리키고 x 축은 수평이며 y 축은 수직입니다. 기본적으로 OpenGL 표준입니다.

큐브를 특정 축의 음의 방향으로 보면 예를 들어 y 축을 내려다 보면 시계 반대 방향으로 회전합니다.

카메라는 음의 z 방향으로 큐브에서 적당한 거리에 z 축에 있어야하고 큐브는 (0; 0; 0)에 있어야합니다. 그만큼. 큐브도 완전히 볼 수 있어야하며 드로잉 프레임의 50 % 이상을 차지해야합니다. 카메라는 큐브에서 양의 z 방향으로보아야합니다.

큐브의 회전은 x-> y-> z 순서로 적용됩니다.

큐브는 중심을 중심으로 회전하며 움직이지 않습니다.

2D 공간에서 큐브를 투영하려면 큐브의 x 및 y 좌표를 점과 카메라 사이의 z 축에 평행 한 거리로 나눠야합니다.

규칙

렌더링 라이브러리는 허용되지만 정점은 코드에서 정의해야합니다. 3D 큐브 모델 클래스가 없습니다.

테스트 사례

여기에 이미지 설명을 입력하십시오



답변

구두 (루비) 235 231

처음부터 모든 것이 계산되었습니다.

Shoes.app{p,a,b,c=ARGV.map{|j|j.to_f/90}
k=1+i="i".to_c
p=(0..3).map{|j|y,z=(k*i**(j+a)).rect
x,z=(((-1)**j+z*i)*i**b).rect
q=(x+y*i)*i**c
[90*(k+q/(z-4)),90*(k+q/(4+z))]}
4.upto(15){|j|line *(p[j%4][0].rect+p[(j+j/4)%4][1].rect)}}

커맨드 라인에서 호출 shoes cube3d.rb 0 30 0

아이디어는 3 차원에서 4 면체의 4 개의 정점을 동시에 생성 / 회전시키는 것입니다. 그런 다음 이것들이 2d로 축소됨에 따라 우리는 4 면체의 정점 4 개를 생성합니다 (총 8 개의 정점은 큐브의 정점입니다). 이것은 4 개의 대각선에 해당하는 4 쌍의 정점을 제공합니다. 마지막으로 2 차원 꼭짓점은 선으로 연결됩니다. 원래 4 면체의 각 꼭짓점은 입방체의 12 개의 가장자리와 4 개의 대각선을 형성하는 역 4 면체의 각 꼭짓점에 연결되어야합니다. 순서는 바디 대각선이 플롯되지 않도록합니다.

테스트 케이스 출력

마지막 두 테스트 사례와 일치하도록 z 축을 중심으로 회전하는 것은 뷰어의 POV에서 시계 방향입니다. 그러나 이것은 사양과 모순되는 것 같습니다. 수정하여 회전 방향을 바꿀 수 있습니다 *i**c->/i**c

언 골프

Shoes.app{
  p,a,b,c=ARGV.map{|j|j.to_f/90}   #Throw away first argument (script name) and translate next three to fractions of a right angle.
  k=1+i="i".to_c                   #set up constants i=sqrt(-1) and k=1+i

  p=(0..3).map{|j|                 #build an array p of 4 elements (each element wil be a 2-element array containing the ends of a body diagonal in complex number format)
    y,z=(k*i**(j+a)).rect          #generate 4 sides of square: 1+i,i-1,-1-i,-i+1, rotate about x axis by a, and store in y and z as reals
    x,z=(((-1)**j+z*i)*i**b).rect  #generate x axis displacements 1,-1,1,-1, rotate x and z about y axis by b, store in x and z as reals
    q=(x+y*i)*i**c                 #rotate x and y about z axis, store result in q as complex number
  [90*(k+q/(z-4)),90*(k+q/(4+z))]} #generate "far" vertex q/(4+z) and "near" vertex q/-(4-z) opposite ends of body diagonal in 2d format.

  4.upto(15){|j|                   #iterate through 12 edges, use rect and + to convert the two complex numbers into a 4 element array for line method
    line *(p[j%4][0].rect+         #cycle through 4 vertices of the "normal" tetrahedron
     p[(j+j/4)%4][1].rect)         #draw to three vertices of the "inverted" tetrahedron. j/4=1,2,3, never 0
  }                                #so the three edges are drawn but the body diagonal is not.
}

역사적 이유로 9 번 줄에 90의 스케일 팩터가 적용되었지만 (골프의 경우 2 번 줄의 90 도와 동일하게 선택됨) 결국이 특정 값을 사용할 때 골프 이점이 없었으므로 임의의 선택.


답변

HTML / CSS / JS, 739 바이트, 아마 비경쟁

그러나 CSS 3D 변환을 보여주고 싶었습니다.

w=_=>o.style.transform=`rotateZ(${z.value}deg) rotateY(${y.value}deg) rotateX(${-x.value}deg)`
input {
  width: 5em;
}

#c{width:90px;height:90px;margin:90px;position:relative;perspective:180px}#o{position:absolute;width:90px;height:90px;transform-style:preserve-3d;transform-origin:45px 45px 0px;}#o *{position:absolute;width:90px;height:90px;border:2px solid black}#f{transform:translateZ(45px)}#b{transform:rotateX(180deg)translateZ(45px)}#r{transform:rotateY(90deg)translateZ(45px)}#l{transform:rotateY(-90deg)translateZ(45px)}#u{transform:rotateX(90deg)translateZ(45px)}#d{transform:rotateX(-90deg)translateZ(45px)}
<div oninput=w()>
  X:<input id="x" type="number" value="0" min="0" max="360">
  Y:<input id="y" type="number" value="0" min="0" max="360">
  Z:<input id="z" type="number" value="0" min="0" max="360">
</div>
<!-- Above code for ease of use of snippet. Golfed version: <div oninput=w()><input id=x><input id=y><input id=z></div> -->

<div id=c><div id=o><div id=f></div><div id=b></div><div id=r></div><div id=l></div><div id=u></div><div id=d>

답변

메이플, 130 + 14 (진행 중)

with(plots):f:=(X,Y,Z)->plot3d(0,x=0..1,y=0..1,style=contour,tickmarks=[0,0,0],labels=["","",""],axes=boxed,orientation=[Z,-X,Y]);

상자 안에 상수 함수를 플로팅 한 다음, 플롯 옵션을 사용하여 눈금, 레이블 및 함수 자체를 숨 깁니다. projection=.5옵션에 추가 하면 카메라를 더 가까이 가져 와서 투시도를 볼 수 있습니다.
나는 스펙이 완성되기 전에 이것을 작성했고 회전 순서는 x, y', z''대신에 x, y, z. 각도를 고칠 때까지 다른 해결책이 있습니다.

POV- 레이, 182

#include"a.txt"
#include"shapes.inc"
camera{location 9*z look_at 0}
light_source{9*z color 1}
object{Wire_Box(<-2,-2,-2>,<2,2,2>,.01,0)texture{pigment{color rgb 1}}rotate<R.x,-R.y,-R.z>}

회전 각도
와 함께 a.txt포함 해야하는 파일을 통해 입력을 읽습니다.
#declare R=<xx,yy,zz>;
xx,yy,zz