ZL31ARM: funkcje graficzne 3D
Teraz można wywoływać tę funkcją podając dwie współrzędne na płaszczyźnie (x,y), 3 kąty obrotu oraz to czy ma być widoczny czy nie.
Ukrywanie niewidocznych krawędzi sześcianu
Jednym ze sposobów nadania bryle solidnej formy jest usunięcie tych krawędzi, które znajdują się z „tyłu”. Zrealizowana tutaj metoda ukrywania tych elementów działa dość dobrze tylko dla sześcianu. W przypadku innych brył należałoby zmodyfikować kod, jednak możliwe, że nie ze wszystkimi rodzajami brył ta metoda będzie współpracować.
Idea polega na tym, aby po obróceniu sześcianu i przed jego wyświetleniem, wyrzucić niepotrzebne krawędzie. Jako, że przyjęty globalny układ jest nieruchomy i jego oś z jest prostopadła i skierowana w stronę wyświetlacza, to zawsze przynajmniej jedna krawędź będzie miała ujemne współrzędne początku i końca w osi z. Przy wyznaczaniu wszystkich takich linii są znajdowane pewne wartości graniczne, dolne i górne w osi x i y. Dzięki nim będzie można określić czy dana krawędź jest widoczna czy nie. Ilustruje to poniższy kod:
signed short xThresDown=0, yThresDown=0, xThresUp=0, yThresUp=0; line3D tempBUF[12]; .. for(i=0, j=0; i < 12; i++){ if( (rotatedCube[i].z1 <= 0) && (rotatedCube[i].z2 <= 0) ){ tempBUF[j++] = rotatedCube[i]; if(rotatedCube[i].x1 > xThresUp) xThresUp = (short) rotatedCube[i].x1; else if(rotatedCube[i].x2 > xThresUp) xThresUp = (short) rotatedCube[i].x2; if(rotatedCube[i].y1 > yThresUp) yThresUp = (short) rotatedCube[i].y1; else if(rotatedCube[i].y2 > yThresUp) yThresUp = (short) rotatedCube[i].y2; if(rotatedCube[i].x1 < xThresDown) xThresDown = (short) rotatedCube[i].x1; else if(rotatedCube[i].x2 < xThresDown) xThresDown = (short) rotatedCube[i].x2; if(rotatedCube[i].y1 < yThresDown) yThresDown = (short) rotatedCube[i].y1; else if(rotatedCube[i].y2 < yThresDown) yThresDown = (short) rotatedCube[i].y2; } }
Następnie należy wyszukać niewidocznych krawędzi:
//Szukaj "widocznych" krawedzi for(i=0; i < 12; i++){ //Odrzuc juz zapamietane krawedzie if( (rotatedCube[i].z1 <= 0) && (rotatedCube[i].z2 <= 0) ) continue; else if( (rotatedCube[i].x1 >= xThresUp || rotatedCube[i].y1 >= yThresUp) && (rotatedCube[i].x2 >= xThresUp || rotatedCube[i].y2 >= yThresUp)) tempBUF[j++] = rotatedCube[i]; else if( (rotatedCube[i].x1 >= xThresUp || rotatedCube[i].y1 >= yThresUp) && (rotatedCube[i].x2 <= xThresDown || rotatedCube[i].y2 <= yThresDown)) tempBUF[j++] = rotatedCube[i]; else if( (rotatedCube[i].x1 <= xThresDown || rotatedCube[i].y1 <= yThresDown) && (rotatedCube[i].x2 >= xThresUp || rotatedCube[i].y2 >= yThresUp)) tempBUF[j++] = rotatedCube[i]; else if( (rotatedCube[i].x1 <= xThresDown || rotatedCube[i].y1 <= yThresDown) && (rotatedCube[i].x2 <= xThresDown || rotatedCube[i].y2 <= yThresDown)) tempBUF[j++] = rotatedCube[i]; }
Nowy zbiór krawędzi jest zapamiętywany w tablicy tempBUF[], która zostanie następnie wyświetlona:
//Rysuj kolejne krawedzie szescianu for(i=0; i < j; i++){ //rotatedCube[i] = tempBUF[i]; drawLine(x0+tempBUF[i].x1,y0+tempBUF[i].y1,x0+tempBUF[i].x2,y0+tempBUF[i].y2,color);