Thread overview
Üç Boyutlu Dünya-3
Dec 16, 2021
Salih Dincer
Dec 19, 2021
Salih Dincer
Jan 18, 2022
Salih Dincer
December 16, 2021

Merhaba,

Bu 3. yazı dizimizde, lafı çok dolandırmadan ve doğrudan Adam D. Ruppe'un SimpleDisplay'i ile başlıyoruz. Bağlantısında verdiğim sayfanın ortalarında da olan aşağıdaki basit örnek, şu an Satır 495'de başladığını görebilirsiniz...(başka örnekler de var!)

Ama Adam'ın çizgisinden biraz kayacağız çünkü sınıflarla çalışacağız. Bunun için hemen alttaki gibi yardımcı bir sınıf ve with() kullanmak yeterli. Bu örneğin (ekrana rasgele renkli çizgiler çizer) satır sayısı artmış gibi dursa da manevra kabiliyeti açısından OpenGL kullanmadan 2D->3D dönüşümü kolaylıkla yapabileceğiz.

class PainterHelper {
  SimpleWindow window;

  this(int width, int height) {
    this.window = new SimpleWindow(width, height, "Random Lines");
  }

  void Draw() {
    with(window.draw()) { // painter
      // random color
      outlineColor = Color(uniform(0, 256), uniform(0, 256), uniform(0, 256));
      // random line
      drawLine(
        Point(uniform(0, window.width), uniform(0, window.height)),
        Point(uniform(0, window.width), uniform(0, window.height))
      );
    }
  }
}

import std.random, arsd.simpledisplay;
void main() {
	auto scr = new PainterHelper(400, 400);
	with(scr) window.eventLoop(100, &Draw);
}/* Compile Paramters:
  ********************
dmd randomLine.d arsd/color.d arsd/simpledisplay.d

  * https://github.com/adamdruppe/arsd/blob/master/color.d
  * https://github.com/adamdruppe/arsd/blob/master/simpledisplay.d
  */

Gördüğünüz gibi main() içinde 2 satır ile kuruluyor ve tek bir işlevin içinde painter ile ilişkili olarak renk tanımlayıp şekil çizebiliyorsunuz. Her şey bu kadar Simple (kolay!)

Lütfen bu kodu, ilgili 2 dosyasını arsd dizinine kopyalayıp hemen derleyin ve düşüncelerinizi paylaşın. Çok yakında 3B küpümüzü ve hayallerimiz ile sınırlı üç boyutlu dünyaya sağlam bir zıplama yapacağız :)

Başarılar...

December 19, 2021

On Thursday, 16 December 2021 at 12:57:54 UTC, Salih Dincer wrote:

>

Çok yakında 3B küpümüzü ve hayallerimiz ile sınırlı üç boyutlu dünyaya sağlam bir zıplama yapacağız :)

Bir haftadır birkaç başlık altında 3B dünyaya adım atmaya çalışıyorduk. Birlikte kodu geliştirip istediğimiz seviyeyi (derinliği olan 3 farklı nesneyi belli bir eksende döndürmeyi) sağladık...

Sonraki versiyonla bu kodu (ekrana 1 tane dörtyüzlü, 1 tane beş yüzü bulunan piramiti ve 5 tane de küp çizer) drawLine() ile değil de drawPolygon() ile yaparsanız çizgiler yerine içi dolu yüzeyler ile çalışabilmeniz mümkün. Başarılar..

  import arsd.simpledisplay, std.stdio;
  import std.algorithm, std.range;
  import std.math, std.random;

  enum windowWidth  = 1200;
  enum windowHeight = 640;
  enum katSayı = 30;
  enum açı = 6;
  enum fps = katSayı * açı;

enum Boyut { X, Y, Z }

struct Nodes { double x, y, z; }

class PainterHelper {
  SimpleWindow window;
  Color backgroundColor;
  Shape[] shapes;

  this(int width, int height, string name, Color color = Color.black) {
    this.window = new SimpleWindow(width, height, name);
    this.backgroundColor = color;
    window.draw.clear(backgroundColor);

    shapes ~= new Tetrahedron(Nodes(-450, -200, -100), 100);
    shapes ~= new Polyhedron(Nodes(-200, -200, -100), 100);//*
    for(double x = 0, b = 25; x <= 500; x += 125, b += 15)
    {
      shapes ~= new Cube(Nodes(x, -200, -100), b);
    }//*/

    foreach(shape; shapes) {  // Initialize rotate
      shape.rotate(açı, Boyut.X);
      shape.rotate(açı, Boyut.Y);
      shape.rotate(açı, Boyut.Z);
    }
  }

  void Draw() {
    with(window.draw) {
      clear(backgroundColor);
      SetOrigin(Point(windowWidth/2, windowHeight/2));
      foreach(shape; shapes) {
        shape.rotate(açı, Boyut.Y);
        shape.transform();

        /*
        outlineColor = Color.red;
        fillColor = Color.red;
        foreach(point; shape.nodes) {
          drawCircle(
            Point(cast(int)point.x-2, cast(int)point.y-2), 4
          );
        }//*/

        foreach(point; shape.kenar) {
          point.XY.writeln(", ", point.EB);
          outlineColor = point.rengi;
          drawLine(point.XY, point.EB);
        }
      }
    }
  }
}

class Shape {
  Nodes[9] nodes;

  this(Nodes p, double b) {
    auto boyut = Nodes(b, b, b);
    nodes[0] = Nodes(p.x - boyut.x, p.y - boyut.y, p.z - boyut.z); // A1 Köşesi (-)(-)(-)
    nodes[1] = Nodes(p.x - boyut.x, p.y - boyut.y, p.z + boyut.z); // B1 Köşesi (-)(-)(+)
    nodes[2] = Nodes(p.x - boyut.x, p.y + boyut.y, p.z - boyut.z); // A0 Köşesi (-)(+)(-)
    nodes[3] = Nodes(p.x - boyut.x, p.y + boyut.y, p.z + boyut.z); // B0 Köşesi (-)(+)(+)
    nodes[4] = Nodes(p.x + boyut.x, p.y - boyut.y, p.z - boyut.z); // D1 Köşesi (+)(-)(-)
    nodes[5] = Nodes(p.x + boyut.x, p.y - boyut.y, p.z + boyut.z); // C1 Köşesi (+)(-)(+)
    nodes[6] = Nodes(p.x + boyut.x, p.y + boyut.y, p.z - boyut.z); // D0 Köşesi (+)(+)(-)
    nodes[7] = Nodes(p.x + boyut.x, p.y + boyut.y, p.z + boyut.z); // C0 Köşesi (+)(+)(+)
    nodes[8] = Nodes(p.x, p.y, p.z); // Şeklin Merkezi
  }

  void ekseniDöndürüpUyarla(Boyut eksen) {
    rotate(açı, eksen);
    transform();
  }

  void rotate(int angle, Boyut dimension) {
    auto angleTheta = cast(double)angle;
    Nodes cosTheta, sinTheta;

    foreach(ref node; nodes) {
      if(dimension == Boyut.X || dimension == Boyut.Z) {
        cosTheta.x = node.x * cos(angleTheta);
        sinTheta.x = node.x * sin(angleTheta);
      }
      if(dimension == Boyut.Y || dimension == Boyut.Z) {
        cosTheta.y = node.y * cos(angleTheta);
        sinTheta.y = node.y * sin(angleTheta);
      }
      if(dimension == Boyut.X || dimension == Boyut.Y) {
        cosTheta.z = node.z * cos(angleTheta);
        sinTheta.z = node.z * sin(angleTheta);
      }
      if(dimension == Boyut.X) {
          node.x = cosTheta.x + sinTheta.z;
          node.z = cosTheta.z - sinTheta.x;
      }
      if(dimension == Boyut.Y) {
          node.y = cosTheta.y - sinTheta.z;
          node.z = cosTheta.z + sinTheta.y;
      }
      if(dimension == Boyut.Z) {
          node.x = cosTheta.x - sinTheta.y;
          node.y = cosTheta.y + sinTheta.x;
      }
    }
  }
  abstract void transform();
  abstract Çizgi[] kenar();
}

struct Çizgi {
  Point XY;
  Point EB;
  Color rengi;

  this(Nodes XY, Nodes EB, Color c) {
    this.XY.x = cast(int)XY.x;
    this.XY.y = cast(int)XY.y;
    this.EB.x = cast(int)EB.x;
    this.EB.y = cast(int)EB.y;
    this.rengi = c;
  }
}

class Tetrahedron : Shape {
  Çizgi[6] edges;
  Color c;

  this(Nodes konum, double boyut, Color c = Color.gray) {
    super(konum, boyut);
    this.c = c;
  }

  override void transform() {
    edges[0] = Çizgi(nodes[5], nodes[6], c);
    edges[1] = Çizgi(nodes[5], nodes[0], c);
    edges[2] = Çizgi(nodes[5], nodes[3], c);
    edges[3] = Çizgi(nodes[3], nodes[6], c);
    edges[4] = Çizgi(nodes[6], nodes[0], c);
    edges[5] = Çizgi(nodes[0], nodes[3], c);
  }
  override Çizgi[] kenar() { return edges; }
}

class Polyhedron : Shape {
  Çizgi[8] edges;
  Color c;

  this(Nodes konum, double boyut, Color c = Color.gray) {
    super(konum, boyut);
    this.c = c;
  }

  override void transform() { // 8 Çizgi
    edges[0] = Çizgi(nodes[2], nodes[8], c); // A Köşesi (dikmesi)
    edges[1] = Çizgi(nodes[3], nodes[8], c); // B Köşesi (dikmesi)
    edges[2] = Çizgi(nodes[7], nodes[8], c); // D Köşesi (dikmesi)
    edges[3] = Çizgi(nodes[6], nodes[8], c); // D Köşesi (dikmesi)
    edges[4] = Çizgi(nodes[2], nodes[3], c); // A Kenarı (A0)
    edges[5] = Çizgi(nodes[3], nodes[7], c); // B Kenarı (B0)
    edges[6] = Çizgi(nodes[7], nodes[6], c); // C Kenarı (C0)
    edges[7] = Çizgi(nodes[6], nodes[2], c); // D Kenarı (D0)
  }
  override Çizgi[] kenar() { return edges; }
}

class Cube : Shape {//, IShape {
  Çizgi[12] edges;
  Color c;

  this(Nodes konum, double boyut, Color c = Color.gray) {
    super(konum, boyut);
    this.c = c;
  }

  override void transform() { // 12 Çizgi
    edges[0]  = Çizgi(nodes[0], nodes[1], c);
    edges[1]  = Çizgi(nodes[1], nodes[5], c);
    edges[2]  = Çizgi(nodes[5], nodes[4], c);
    edges[3]  = Çizgi(nodes[4], nodes[0], c);
    //*toogle-switch for perpendiculars/
    edges[4]  = Çizgi(nodes[2], nodes[0], c);
    edges[5]  = Çizgi(nodes[3], nodes[1], c);
    edges[6]  = Çizgi(nodes[7], nodes[5], c);
    edges[7]  = Çizgi(nodes[6], nodes[4], c);
    //toogle-switch perpendiculars*/
    edges[8]  = Çizgi(nodes[2], nodes[3], c);
    edges[9]  = Çizgi(nodes[3], nodes[7], c);
    edges[10] = Çizgi(nodes[7], nodes[6], c);
    edges[11] = Çizgi(nodes[6], nodes[2], c);
  }
  override Çizgi[] kenar() { return edges; }
}

alias Painter = PainterHelper;

void main() {
  auto rnd = Random(41);
  auto scr = new Painter(windowWidth, windowHeight, "Shapes 3D", Color.white);
  with(scr) window.eventLoop(fps, &Draw,
    delegate (KeyEvent event)
    {
      if(event.key == Key.Space)
      {
        auto rasgele = uniform(0, shapes.length);
        shapes[rasgele].ekseniDöndürüpUyarla(Boyut.X);
      }
      else if(event.key == Key.Escape)
      {
        window.close();
      }
    }
  );
}

Not: Boşluk tuşuna basıp rasgele şekilleri ekstra döndürmeniz mümkün.

January 18, 2022

On Sunday, 19 December 2021 at 20:38:40 UTC, Salih Dincer wrote:

>

On Thursday, 16 December 2021 at 12:57:54 UTC, Salih Dincer wrote:

class PainterHelper {
//...
  void Draw() {
    with(window.draw) {
      clear(backgroundColor);
      SetOrigin(Point(windowWidth/2, windowHeight/2));
      foreach(shape; shapes) {
        shape.rotate(açı, Boyut.Y);
        shape.transform();

//...

Helper içinde yukardaki gibi SetOrigin() satırı varmış! Şu sıralar küçük bir GUI tasarlarken elimin altındaki bu kod ile başlamak istedim ama derlenmedi. Bu benim yapmamam gereken bir hataydı, hemen düzeltiyorum:

Orijinalindeki L8598 numaralı satıra kolaylık olsun diye masumane bir eklem yapmıştım. Bu bir virüs gibi kodlar arasında ilerlemiş :(

Oradaki kodlar şöyleydi:

	@property int originX() { return _originX; }
	@property int originY() { return _originY; }
	@property int originX(int a) {
		_originX = a;
		return _originX;
	}
	@property int originY(int a) {
		_originY = a;
		return _originY;
	}

Ben ise 2 işlevi tek satırada yazabilmek için birleştirmiştim:

  @property void SetOrigin(Point origin) {
      originX = origin.x;
      originY = origin.y;
  }

Herkesten özür diliyorum, forumda yazdıklarımız düzeltilemediği için bu şekilde telafi yoluna gittim. Nasıl kullanmak isterseniz açık seçik yukardaki gibi ortada.

Başarılar...