Stm32f4 - 3D Kütüphanesi #3 (Farklı Objelerin Üretilmesi)

Bu yazımda küp dışındaki bazı geometrik cisimlerin tel-kafes yöntemi ile nasıl üretebileceğimizi göstereceğim.

1.Dikdörtgen Prizma

Küpteki tek bir kenarının uzunluğu olan "Uzunluk" argümanı yerine "a, b, c" argümanları yazarak her bir kenarın uzunlğunu ayrı ayrı tanımlayabiliriz. Her bir köşenin koordinatları şu şekilde olacaktır :

prizma

Bunu fonksiyon şeklinde yazarsak :

/**@Tanım : Istenen buyuklukte, koordinatta ve renkte prizma yaratan fonksiyon
  *@Parametreler : Prizma = yaratilmak istenen Objenin adresi,
  *                x, y, z = Objenin koordinatlari
  *                a, b, c = Prizmanin her bir kenarinin uzunlugu
  *                Renk = Objenin cizgilerinin rengi
  */ 
void GL_3DDikdortgenPrizma(GL_Obje *Prizma, float x, float y, float z, double a, float b, float c, uint16_t Renk)
{    
    //Noktalari olustur
    float Prizma_Noktaklari[8][3] = {
        x,       y,      z,
        x + a,   y,      z,
        x + a,   y,      z + c,
        x,       y,      z + c,
        x,       y + b,  z,
        x + a,   y + b,  z,
        x + a,   y + b,  z + c,
        x,       y + b,  z + c };
    
    //Hangi noktalarin birbiri ile birlesecegini belirle
    uint16_t Prizma_Cizgileri[12][2] = {
        0, 1,
        1, 2,
        2, 3,
        3, 0,    
        4, 5,
        5, 6,
        6, 7,
        7, 4,        
        0, 4,
        1, 5,
        2, 6,
        3, 7
    };
        
    //Noktalar ve Cizgiler icin dinamik bellekte yer ayir ve onceden hesaplanmis
    //degerleri bu ayrilan yere kopyala    
    float *_Prizma_Noktalari = (float *)malloc(sizeof(Prizma_Noktaklari));
    memcpy(_Prizma_Noktalari, Prizma_Noktaklari, sizeof(Prizma_Noktaklari));
    
    uint16_t *_Prizma_Cizgileri = (uint16_t *)malloc(sizeof(Prizma_Cizgileri));
    memcpy(_Prizma_Cizgileri, Prizma_Cizgileri, sizeof(Prizma_Cizgileri));
    
    //Hesaplanan butun degerleri Prizma'ya at
    Prizma->NoktaSayisi = 8;
    Prizma->CizgiSayisi = 12;
    Prizma->Noktalar = (float (*)[3])_Prizma_Noktalari;
    Prizma->Cizgiler = (uint16_t (*)[2])_Prizma_Cizgileri;
    Prizma->Koordinat[0] = x;
    Prizma->Koordinat[1] = y;
    Prizma->Koordinat[2] = z;
    Prizma->Merkez[0] = x + a / 2;
    Prizma->Merkez[1] = y + b / 2;
    Prizma->Merkez[2] = z + c / 2;
    Prizma->Renk = Renk;
}

2.Piramit

Piramit içinde yukarıdaki gibi bir şekil çizilip her bir köşenin koordinatı hesaplanak aşağıdaki gibi bir fonksiyon yazılabilir.

/**@Tanım : Istenen buyuklukte, koordinatta ve renkte piramit yaratan fonksiyon
  *@Parametreler : Piramit = yaratilmak istenen Objenin adresi,
  *                x, y, z = Objenin koordinatlari
  *                a, b = Piramitin her bir kenarinin uzunlugu
  *                h = Piramitin yüksekligi
  *                Renk = Objenin cizgilerinin rengi
  */ 
void GL_3DPiramit(GL_Obje* Piramit, float x, float y, float z, double a, float b, float h, uint16_t Renk)
{        
    //Noktalari olustur
    float Piramit_Noktalari[5][3] = {
        x,          y,      z,
        x + a,      y,      z,
        x + a,      y,      z + b,
        x,          y,      z + b,
        x + a / 2,  y + h,  z + b / 2};
    
    //Hangi noktalarin birbiri ile baglanacagini belirle
    uint16_t Piramit_Çizgileri[8][2] = {
        0, 1,
        1, 2,
        2, 3,
        3, 0,
        0, 4,
        1, 4,
        2, 4, 
        3, 4};
    
    //Noktalar ve Cizgiler icin dinamik bellekte yer ayir ve onceden hesaplanmis
    //degerleri bu ayrilan yere kopyala
    float *_Piramit_Noktalari = (float *)malloc(sizeof(Piramit_Noktalari));
    memcpy(_Piramit_Noktalari, Piramit_Noktalari, sizeof(Piramit_Noktalari));
    
    uint16_t *_Piramit_Çizgileri = (uint16_t *)malloc(sizeof(Piramit_Çizgileri));
    memcpy(_Piramit_Çizgileri, Piramit_Çizgileri, sizeof(Piramit_Çizgileri));
    
    //Hesaplanan butun degerleri Piramat'e at
    Piramit->NoktaSayisi = 8;
    Piramit->CizgiSayisi = 12;
    Piramit->Noktalar = (float (*)[3])_Piramit_Noktalari;
    Piramit->Cizgiler = (uint16_t (*)[2])_Piramit_Cizgileri;
    Piramit->Koordinat[0] = x;
    Piramit->Koordinat[1] = y;
    Piramit->Koordinat[2] = z;
    Piramit->Merkez[0] = x + a / 2;
    Piramit->Merkez[1] = y + h / 2;
    Piramit->Merkez[2] = z + b / 2;
    Piramit->Renk = Renk;
}

3.Silindir

Silindir yaratmak için taban ve tavana birer daire çizip bunları birleştirmek yeterlidir. 2-boyutlu koordinat sisteminde \(a\) açılı ve \(r\) uzunluğundaki bir \(A\) noktasının koordinatı şu şekilde bulunur :

silindir

\(n\) çözünürlük olmak üzere \(a_{i}=\frac{360^{\circ}\,i}{n-1}\) , \(0\leq i < n\) açılı noktaların birleşimi ile \(n\) çözünürlükte bir çember elde edilir.

/**@Tanım : Istenen buyuklukte, koordinatta ve renkte silindir yaratan fonksiyon
  *@Parametreler : Silindir = Yaratilmak istenen Objenin adresi
  *                Cozunurluk = Objenin kenar sayisi
  *                x, y, z = Objenin koordinatlari
  *                Uzunluk = Silindirin uzunlugu
  *                Yaricap = Silindirin yaricapi
  *                Renk = Objenin cizgilerinin rengi
  */ 
void GL_3DSilindir(GL_Obje* Silindir, int Cozunurluk, float x, float y, float z, float Uzunluk, float Yaricap, uint16_t Renk)
{    
    //Silindirin merkez koordinatlarini belirle
    Silindir->Merkez[0] = x;
    Silindir->Merkez[1] = y + Uzunluk / 2;
    Silindir->Merkez[2] = z;
    
    //Silindirin koordinatlarini belirle
    Silindir->Koordinat[0] = x;
    Silindir->Koordinat[1] = y;
    Silindir->Koordinat[2] = z;
    
    //Noktalar ve Cizgiler icin dinamik bellekte yer ayir
    float *_Silindir_Noktalari = (float *)malloc((Cozunurluk * 2) * sizeof(float) * 3);    
    uint16_t *_Silindir_Cizgileri = (uint16_t *)malloc((3 * Cozunurluk) * sizeof(uint16_t) *  2);
    
    //NoktaSayisi, CizgiSayisi gibi elemanlari Silindir'e at
    Silindir->NoktaSayisi = Cozunurluk * 2;
    Silindir->CizgiSayisi = 3 * Cozunurluk;
    Silindir->Noktalar = (float (*)[3])_Silindir_Noktalari;
    Silindir->Cizgiler = (uint16_t (*)[2])_Silindir_Cizgileri;
    Silindir->Renk = Renk;
    
    //Noktalarin belirlenmesi
    for(int i = 0; i < Cozunurluk; i++)     {         //Alt tabanin noktalari         Silindir->Noktalar[i][0] = x + Yaricap * cos((float)2 * PI * i / Cozunurluk);
        Silindir->Noktalar[i][1] = y;
        Silindir->Noktalar[i][2] = z + Yaricap * sin((float)2 * PI * i / Cozunurluk);
        
        //Ust tavanin noktalari
        Silindir->Noktalar[i + Cozunurluk][0] = x + Yaricap * cos((float)2 * PI * i / Cozunurluk);
        Silindir->Noktalar[i + Cozunurluk][1] = y + Uzunluk; //Ust tavan icin y'ye Uzunluk ekle
        Silindir->Noktalar[i + Cozunurluk][2] = z + Yaricap * sin((float)2 * PI * i / Cozunurluk);
    }
    
    //Noktalarin birleştirilmesi
    for(int i = 0; i < Cozunurluk; i++)     {         //Alt taban noktalarinin birlestirilmesi         Silindir->Çizgiler[i][0] = i;
        Silindir->Çizgiler[i][1] = (i + 1) % Cozunurluk;
        
        //Ust tavan noktalarinin birlestirilmesi
        Silindir->Çizgiler[i + Cozunurluk][0] = i + Cozunurluk;
        Silindir->Çizgiler[i + Cozunurluk][1] = (i + 1) % Cozunurluk + Cozunurluk;
        
        //Alt taban ile ust tavan arasındaki noktalarin birlestirilmesi
        Silindir->Çizgiler[i + 2 * Cozunurluk][0] = i;
        Silindir->Çizgiler[i + 2 * Cozunurluk][1] = i + Cozunurluk;
    }
}

4.Küre

Kürenin koordinatlarının hesaplanması için silindirde yapılan işlemin 3D olarak yapılması gerekir.

kure

\(a\) ve \(b\) açılarının tarayacağı alan ise şu şekildedir :

acitarama

\(0 < a \leq 2 \pi\), \(0 < b \leq \pi\)

/**@Tanım : Istenen buyuklukte, koordinatta ve renkte kure yaratan fonksiyon
  *@Parametreler : Kure = Yaratilmak istenen Objenin adresi
  *                YuzukSayisi = Kuredeki yatay ve dikey yuzuk sayisi (Cozunurluk)
  *                x, y, z = Objenin koordinatlari
  *                Yaricap = Kurenin yaricapi
  *                Renk = Objenin cizgilerinin rengi
  */ 
void GL_3DKure(GL_Object* Kure, int YuzukSayisi, float x, float y, float z, float Yaricap, uint16_t Renk)
{        
    //Merkez noktalarinin belirle
    Kure->Merkez[0] = x;
    Kure->Merkez[1] = y;
    Kure->Merkez[2] = z;
    
    //Koordinatlari belirle
    Kure->Koordinat[0] = x;
    Kure->Koordinat[1] = y;
    Kure->Koordinat[2] = z;
    
    //Noktalar ve Cizgiler icin dinamik bellekte yer ayir
    float *_Kure_Noktalari = (float *)malloc((YuzukSayisi * (YuzukSayisi + 1)) * sizeof(float) * 3);
    uint16_t *_Kure_Cizgileri = (uint16_t *)malloc((2 * YuzukSayisi * YuzukSayisi - YuzukSayisi) * 2 *  2);

    //NoktaSayisi, CizgiSayisi gibi elemanlari Kure'ye at
    Kure->NoktaSayisi = YuzukSayisi * (YuzukSayisi + 1);
    Kure->CizgiSayisi = 2 * YuzukSayisi * YuzukSayisi - YuzukSayisi;
    Kure->Noktalar = (float (*)[3])_Kure_Noktalari;
    Kure->Cizgiler = (uint16_t (*)[2])_Kure_Cizgileri;
    Kure->Renk =Renk;
    
    //Noktalrin koordinatlarini hesapla
    for(int i = 0; i < YuzukSayisi; i++)
    {
        for(int j = 0; j < (YuzukSayisi + 1); j++)         {             Kure->Noktalar[i * (YuzukSayisi + 1) + j][0] = x + Yaricap * cos((float)2 * PI * i / YuzukSayisi) * sin(PI * j / YuzukSayisi);
            Kure->Noktalar[i * (YuzukSayisi + 1) + j][1] = y + Yaricap * sin((float)2 * PI * i / YuzukSayisi) * sin(PI * j / YuzukSayisi);
            Kure->Noktalar[i * (YuzukSayisi + 1) + j][2] = z + Yaricap * cos(PI * j / YuzukSayisi);
        }
    }
    
    for(int i = 0; i < YuzukSayisi; i++)
    {
        for(int j = 0; j < YuzukSayisi; j++){             
            //Dikey yuzukleri birlestir             
            Kure->Cizgiler[j + i * YuzukSayisi][0] = j + i * (YuzukSayisi + 1);
            Kure->Cizgiler[j + i * YuzukSayisi][1] = j + i * (YuzukSayisi + 1) + 1;
        
            //Yatay yuzukleri birlestir
            Kure->Cizgiler[j + i * YuzukSayisi + YuzukSayisi * YuzukSayisi][0] = j * (YuzukSayisi + 1) + i + 1;
            Kure->Cizgiler[j + i * YuzukSayisi + YuzukSayisi * YuzukSayisi][1] = ((j + 1) * (YuzukSayisi + 1)) % (YuzukSayisi * YuzukSayisi + YuzukSayisi) + i + 1;
        }
    }
}

Test videosu:

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir