Javascript

3 boyutlu dönen küp çizimi

Tarayıcılarda çalışabilirliği olsun, esnek yapısı olsun javascript en sevdiğim programlama dillerinden bir tanesidir. Hatta web sitemin header kısmında gördüğünüz resim bile javascript ile yazdığım 3 boyutlu simülasyondan alınmıştır. Tabi bu simülasyonu yazmak benim için o kadar kolay olmamıştır. Onlarca başarısız denemeden ve aylarca verilen aradan sonra, internette tesadüfen gördüğüm basit bir formül beni tekrar sahalara döndürmüştür. 🙂

“x’ = x*cos(theta) – y*sin(theta)

y’ = x*sin(theta) + y*cos(theta)”

Bu formül, sonraki 3d projelerimizin ayrılmaz bir parçası olacak. Şimdi kodlamaya başlıyoruz. Küpü inşa etmeden önce vektör isimli bir obje tanımlamamız lazım, herşey adım adım.

function vector(x = 0,y = 0,z = 0){
 this.x = x;
 this.y = y;
 this.z = z;
}

Bir küp 8 köşe noktası içerir, her köşesini bir konum vektörü ile temsil edeceğiz.

function cube(size){
 this.coords = [];
 //köşegenler
 this.coords[0] = new vector(0,0,0);
 this.coords[1] = new vector(size,0,0);
 this.coords[2] = new vector(0,size,0);
 this.coords[3] = new vector(size,size,0);
 this.coords[4] = new vector(0,0,size);
 this.coords[5] = new vector(size,0,size);
 this.coords[6] = new vector(0,size,size);
 this.coords[7] = new vector(size,size,size);
 //döndürme fonksiyonu
 this.rotate = function(type,angle){
  for(i = 0;i < this.coords.length;i++){
   var v = this.coords[i];
   var x = v.x;
   var y = v.y;
   var z = v.z;
   switch(type){
    case "x" :
    v.y = y*Math.cos(angle) - z*Math.sin(angle);
    v.z = y*Math.sin(angle) + z*Math.cos(angle);
    break;
    case "y" :
    v.x = x*Math.cos(angle) - z*Math.sin(angle);
    v.z = x*Math.sin(angle) + z*Math.cos(angle);
    break;
    case "z" :
    v.x = x*Math.cos(angle) - y*Math.sin(angle);
    v.y = x*Math.sin(angle) + y*Math.cos(angle);
    break;
   }
  }
 }
}

Artık elimizde bir köşesi (0,0,0) noktasına sabitlenmiş döndürülebilir bir küp var. Son olarak bu küpü milisaniyeler içerisinde tekrar tekrar çizip döndürecek ve animasyon haline sokacak bir fonksiyona ve üzerinde çizim yapabileceğimiz bir canvas elementine ihtiyacımız var. Canvas elementini script taglarının hemen arkasına koyabilirsiniz.

var cube = new cube(100,document.getElementById("myCanvas"));
function animate(cube){
 var c = document.getElementById("myCanvas");
 var ctx = c.getContext("2d");
 ctx.beginPath();
 ctx.clearRect(0,0,c.width,c.height);
 //kübü sayfanın ortasına taşımak için
 ctx.translate(c.width / 2,c.height / 2);
 cube.rotate("x",0.1);
 cube.rotate("y",0.1);
 cube.rotate("z",0.1);
 cube.coords.forEach(function(v){
  ctx.moveTo(v.x,v.y);
  ctx.arc(v.x,v.y,3,0,2*Math.PI);
 });
 ctx.fill();
 ctx.resetTransform();
}
setInterval(function(){animate(cube)},30);

Bir nokta etrafında dönen 8 nokta elde ettik, dönerken küp olduğunu sezebiliyoruz ama yeterli değil. O noktaları kenarlar ile birleştirmemiz lazım. Animate fonksiyonunda yapacağımız birkaç değişiklik bizim için yeterli olacaktır. Aşağıda yorum satırları arasında gördüğünüz kod, küpün 8 köşesini çizerken, altında yer alan yeni kod küpün kenarlarını çizmemizi sağlıyor. Eski kodu yenisi ile değiştirebilir veya ikisini birden tutabilirsiniz.

/*
 cube.coords.forEach(function(v){
  ctx.moveTo(v.x,v.y);
  ctx.arc(v.x,v.y,3,0,2*Math.PI);
 });
*/
var v = cube.coords;
ctx.moveTo(v[0].x,v[0].y);
ctx.lineTo(v[1].x,v[1].y);
ctx.lineTo(v[3].x,v[3].y);
ctx.lineTo(v[2].x,v[2].y);
ctx.lineTo(v[0].x,v[0].y);
ctx.lineTo(v[4].x,v[4].y);
ctx.lineTo(v[5].x,v[5].y);
ctx.lineTo(v[7].x,v[7].y);
ctx.lineTo(v[6].x,v[6].y);
ctx.lineTo(v[4].x,v[4].y);
ctx.moveTo(v[1].x,v[1].y);
ctx.lineTo(v[5].x,v[5].y);
ctx.moveTo(v[2].x,v[2].y);
ctx.lineTo(v[6].x,v[6].y);
ctx.moveTo(v[3].x,v[3].y);
ctx.lineTo(v[7].x,v[7].y);
 
 

Kodun tam haline github sayfamdan ulaşabilirsiniz : https://github.com/farukcansaglam/CubeProject/

Leave a Reply

Your email address will not be published. Required fields are marked *