Narysuj prostą kostkę

10

Nie mamy ani jednego wyzwania dotyczącego narysowania prawdziwej trójwymiarowej kostki, więc oto:

Wyzwanie

Twoim zadaniem jest narysowanie obróconego sześcianu z perspektywą. Może znajdować się w osobnym oknie lub jako obraz.

Wejście

Wprowadzono 3 oddzielne liczby od 0 do 359,99 ... Przedstawiają obrót wokół osi x, y i z w stopniach.

0 0 0
30 0 40
95 320 12

Wynik

Możesz wyświetlić go w osobnym oknie lub zapisać obraz. Możesz użyć dowolnego rodzaju wyświetlacza (oparty na wektorach, zrasteryzowany itp.).

Edycja: ASCII jest również dozwolony, aby zezwolić na języki gry w golfa z tylko tekstem.

Dane wyjściowe dla grafiki rasteryzowanej lub ASCII muszą wynosić co najmniej 50 * 50 (piksele dla rasteryzacji, znaki dla ASCII)

Dodatkowe informacje

Dodatnia oś Z wskazuje okno, oś X jest pozioma, a oś Y jest pionowa. Zasadniczo standard OpenGL.

Obracanie odbywa się w kierunku przeciwnym do ruchu wskazówek zegara, jeśli spojrzysz na sześcian w kierunku ujemnym określonej osi, np. Patrząc w dół w kierunku osi y.

Kamera powinna znajdować się na osi Z w rozsądnej odległości od sześcianu w ujemnym kierunku Z, sześcian powinien znajdować się w (0; 0; 0). The. sześcian musi być również w pełni widoczny i zajmować co najmniej 50% ramki rysunkowej. Kamera powinna patrzeć w sześcian w kierunku dodatnim.

Obroty sześcianu są stosowane w kolejności x-> y-> z.

Sześcian jest obracany wokół środka, nie porusza się.

Aby rzutować sześcian na przestrzeń 2d, musisz podzielić współrzędne xiy sześcianu z odległością równoległą do osi Z między punktem a kamerą.

Zasady

Biblioteki renderowania są dozwolone, ale wierzchołki muszą być zdefiniowane w kodzie. Brak klasy modelu kostki 3d.

Przypadki testowe

wprowadź opis zdjęcia tutaj

Bálint
źródło
1
Czy to musi być szkielet?
Rɪᴋᴇʀ
Chcesz załączyć algorytm dla punktów?
Leaky Nun
3
W jakiej kolejności / kierunkach wykonywane są obroty? Skąd patrzy aparat? Jakiego rodzaju projekcji musimy użyć?
flawr
6
Ale jak powiedziałem, obroty się nie sprawdzą. Jak już zdefiniowałeś, sześcian zostanie przesunięty poza pole widzenia, jeśli np. Zostanie obrócony wokół osi x. Proszę użyć piaskownicy .
flawr
6
@ EᴀsᴛᴇʀʟʏIʀᴋ google will tell you the formula. Nie , wyzwania powinny zawierać jak najwięcej materiałów i informacji potrzebnych do ich rozwiązania, zawartych w treści postu . Nie powinienem iść na googling lub na Wikipedię, żeby zacząć rozumieć.
kot

Odpowiedzi:

2

Buty (rubinowe) 235 231

Wszystko obliczone od zera.

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)}}

Zadzwoń z wiersza poleceń np shoes cube3d.rb 0 30 0

Chodzi o to, aby jednocześnie generować / obracać cztery wierzchołki czworościanu w 3D. Następnie, gdy zostaną one zredukowane do 2d, generujemy cztery wierzchołki odwrotnego czworościanu (łącznie 8 wierzchołków to te sześcianu). Daje to 4 pary wierzchołków odpowiadające 4 przekątnym ciała. Wreszcie 2d wierzchołki są połączone liniami: każdy wierzchołek pierwotnego czworościanu musi być połączony z każdym wierzchołkiem odwrotnego czworościanu, tworząc 12 krawędzi i 4 przekątne bryły sześcianu. Kolejność zapewnia, że ​​przekątne korpusu nie zostaną narysowane.

Dane wyjściowe przypadków testowych

Zauważ, że aby zachować spójność z dwoma ostatnimi przypadkami testowymi, obrót wokół osi Z odbywa się zgodnie z ruchem wskazówek zegara od POV przeglądarki. Wydaje się to jednak być sprzeczne ze specyfikacją. Kierunek obrotu można odwrócić, modyfikując *i**c->/i**c

wprowadź opis zdjęcia tutaj

bez golfa

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.
}

Należy pamiętać, że ze względów historycznych w linii 9 stosuje się współczynnik skali 90 (wybrano, aby był taki sam jak 90 stopni w linii 2 dla gry w golfa), ale ostatecznie nie było żadnej przewagi golfowej w korzystaniu z tej konkretnej wartości, więc stała się dowolny wybór.

Level River St
źródło
3

HTML / CSS / JS, 739 bajtów, prawdopodobnie niekonkurencyjny

Ale chciałem tylko pochwalić się transformacjami CSS 3D.

Neil
źródło
To właściwie wygląda całkiem schludnie. Doświadczyłem wcześniej transformacji CSS3, ale miałem z tym problemy.
Bálint
Wygląda na to, że obroty są w niewłaściwej kolejności. Powinno to być x, a następnie y. Masz z, a następnie y, a następnie x. @ Bálint może potwierdzić.
Level River St
@LevelRiverSt Kiedy to napisałem, nie wiedziałem, jaka powinna być kolejność, i nie mogłem tego wypracować na podstawie przypadków testowych, więc dziękuję za aktualizację. Zmieniłem również kierunek obrotu X, więc teraz dopasowuję wszystkie przypadki testowe.
Neil
Czy nadal możesz podać liczbę bajtów? Nawet jeśli odpowiedzi nie są konkurencyjne, zawsze powinny mieć liczbę bajtów
Downgoat
@Downgoat Gra w golfa lub bez golfa?
Neil
0

Klon, 130 + 14 (w trakcie)

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]);

wprowadź opis zdjęcia tutaj

Wypisuje stałą funkcję w ramce, a następnie używa opcji drukowania do ukrycia znaczników, etykiet i samej funkcji. Dodanie projection=.5do opcji przybliża kamerę, umożliwiając widok perspektywiczny.
Napisałem to, zanim specyfikacje zostały sfinalizowane, a kolejność rotacji jest x, y', z''zamiast x, y, z. Dopóki nie poprawię kątów, oto inne rozwiązanie

POV-Ray, 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>}

czyta wejście za pośrednictwem a.txtpliku, który powinien zawierać
#declare R=<xx,yy,zz>;
z xx,yy,zzczym kąty obrotu

wprowadź opis zdjęcia tutaj

DenDenDo
źródło
1
Tak, za używanie POV-ray, to świetny program. Niestety, reguły mówią teraz, że nie można użyć żadnej klasy kostki 3d.
mil