ZL31ARM: funkcje graficzne 3D
Aby przez cały czas wyświetlać obracającą się bryłę wraz z możliwością przełączania względem której osi dokonywać obrót należy wykonać poniższy kod:
while(1){ Delay(0xFFFF); if(GPIO_ReadInputDataBit(JOY_PORT_OK, JOY_OK) == 0){ if(++modeSelect == 3) modeSelect = 0; //Czekaj do odpuszczenia przycisku while(GPIO_ReadInputDataBit(JOY_PORT_OK, JOY_OK) == 0); } switch(modeSelect){ case 0:{ x += 5; break; } case 1:{ y += 5; break; } case 2:{ z += 5; break; } } //Usun poprzedni szescian drawCube(0, 0, xo, yo, zo, 0x0); //Rysuj nowy szescian drawCube(0, 0, x, y, z, 0xFFF); //Zachowaj stare wartosci katow xo = x; yo = y; zo = z; }
Tetrahedron, dodekahedron…
Opierając się na przedstawionym dotychczas materiale wraz z opisaną metodą realizacji rysowania prostej bryły nic nie stoi na przeszkodzie wyświetlania innych brył. Dla przykładu można narysować tetrahedron, który ma 4 wierzchołki i 6 krawędzi. W tym celu wystarczy zdefiniować 2 tablicy (tak jak w przypadku sześcianu):
line3D rotatedTH[6], tetraHedron[6]={ { 0, 0, 0, 0, 0,-30}, { 0, 0, 0, 0, 30, 0}, { 0, 0, 0, 30, 0, 0}, { 30, 0, 0, 0, 0,-30}, { 30, 0, 0, 0, 30, 0}, { 0, 30, 0, 0, 0,-30} };
oraz dodać dodatkową funkcję:
void drawTetraHedron(int x0, int y0, unsigned char x_angle, unsigned char y_angle, unsigned char z_angle, unsigned int color){ unsigned char i; //Obroc wszystkie 12 krawedzi szescianu for (i=0; i < 6; i++) rotateLine(tetraHedron[i], &(rotatedTH[i]), x_angle, y_angle, z_angle); //Rysuj kolejne krawedzie szescianu for(i=0; i < 6; i++) drawLine(x0 + rotatedTH[i].x1, y0 + rotatedTH[i].y1, x0 + rotatedTH[i].x2, y0 + rotatedTH[i].y2, color); }
W podobny sposób można budować bardziej skomplikowane figury, poprzez podanie tylko tablicy z określonymi krawędziami oraz funkcji rysującej te krawędzie. Tutaj zostaje już tylko wyobraźnia użytkownika.
Lokalny układ współrzędnych
Czasem podczas animacji jakiegokolwiek obiektu pomocnym może okazać się widok na lokalny układ współrzędnych związany z danym obiektem i obracający się razem z nim. W tym celu należy dodać poniższą funkcję w pliku graphics.c:
void drawLocalXYZ(int x0, int y0, unsigned char x_angle, unsigned char y_angle, unsigned char z_angle, unsigned char visible){ unsigned char i; unsigned short colors[3]={RED,GREEN,BLUE};//Definicja kolorow wersorow //Obroc wszystkie 3 wersowy lokalnego ukladu for(i=0; i < 3; i++) rotateLine(localXYZ[i], &(rotatedLocalXYZ[i]),x_angle,y_angle,z_angle); switch(visible){ //Wyswietl wersowy lokalnego ukladu wspolrzednych case 1:{ for(i=0; i < 3; i++) drawLine(x0+rotatedLocalXYZ[i].x1, y0+rotatedLocalXYZ[i].y1, x0+rotatedLocalXYZ[i].x2, y0+rotatedLocalXYZ[i].y2, colors[i]); break; } //Ukryj wersowy lokalnego ukladu default:{ for(i=0; i < 3; i++) drawLine(x0+rotatedLocalXYZ[i].x1, y0+rotatedLocalXYZ[i].y1, x0+rotatedLocalXYZ[i].x2, y0+rotatedLocalXYZ[i].y2, 0x0); break; } } }
oraz strukturę na początku:
line3D rotatedLocalXYZ[3], localXYZ[3]={ { 0, 0, 0, 20, 0, 0}, { 0, 0, 0, 0, 20, 0}, { 0, 0, 0, 0, 0, 20} };