Bu makalemizde, Three.JS'in lokal ve global koordinat sistemlerini işleyeceğiz ve oyun yapımına bir adım daha yaklaşacağız.

Bir önceki makalemizdeki son örneğimizde, klavyeden bastığımız tuşlarla ekrandaki küpü hareket etmeyi başarmıştık. Bunu sahnedeki arabamız olarak düşünelim ve diyelim ki arabamızın burnu Z eksenine doğru bakıyor. Bu durumda ileri tuşuna bastığımızda arabamızın ileriye doğru hareket etmesi için yapmamız gereken tek şey, nesnemizin sahnedeki z koordinat değerini arttırmak olacaktır, kolay değil mi?

Peki, diyelim ki arabanın burnu X eksenine doğru bakıyor. Bu durumda ileri gitmek için ise, nesnemizin sahnedeki x koordinat değerini arttırmamız gerekecektir, hayat ne güzel.


Bu sefer arabamızın burnu Z ekseni ile X ekseninin tam ortasına doğru bakıyor olsun. Bu durumda ileriye doğru on birimlik hareket edebilmek için ne yapacağız? Üçgenlerden veya trigonometriden faydalanarak Z ve X eksenlerinin her birinde ne kadar gitmemiz gerektiğini hesap ederek aksiyon alabiliriz. Eh, ne de olsa mühendisiz, yapalım o kadarını da.

Pekala, soru geliyor. Arabamız Z eksenine 34.52 derecelik açı yaparken 12.34 derecelik bir yokuşa denk geldi. Artık Z ve X haricinde, bir de Y ekseni karşımıza çıktı. 10 birimlik ileri gidebilmek için, bu üç eksende kaçar birim ve hangi yönde hareket etmemiz gerekir?

Bir adım ileri gidelim. Araba yarışını bir kenara bıraktık ve uçak simülasyonuna geçtik. Karşımızdaki uçak gemisine inmemiz gerekiyor. X, Y ve Z eksenlerinde nasıl bir hareket gerçekleştirmeliyiz ki, uçağımız uçak gemisine doğru gitsin?

Nasıl? Oyun programcılığı yerine muhasebe programı yazmak daha mantıklı gelmeye başladı mı? :)

Telaş etmene gerek yok :) Bu makalemizin konusu, bu sorulara, ruh sağlığımızı korumak şartıyla cevap verecek inşallah. Konumuz lokal ve global koordinat sistemleri.

Not : Benim gibi ilk başlarda lokal koordinat sistemini bilmeyenlere, trigonometri ile bir miktar boğuşmalarını tavsiye ediyorum. Oldukça eğitici oluyor :)

Öncelikle global koordinat sisteminden başlayalım. Aslında bu koordinat sistemi, şimdiye kadar kullandığımız koordinat sistemiydi. Tüm sahne için X, Y ve Z eksenleri mutlaktır ve herhangi bir cismin veya kameranın bakış açısına göre değişmez. Bu durumda bir kutunun sağ tarafı X eksenine doğru bakıyorsa, kutuyu uygun tarafa doğru 90 derece çevirirsek, bu durumda aynı kutunun sağ tarafı Z eksenine doğru bakacaktır.

Lokal koordinat sistemleri ise, sahnedeki nesneler ile tümleşiktir ve onlarla birlikte döner/hareket eder. Aynı örnek üzerinden gidelim. Sahnede bir kutumuzun olduğunu ve kutumuzun sağ yüzeyinin lokal Z eksenine baktığını düşünelim. Ardından bu nesneyi Y ekseni etrafında 20 derece, Z ekseni etrafında 10 derece, X ekseni etrafında da 40 derece çevirdiğimizi varsayalım. Tüm bu dönüş işlemleri, nesne ile birlikte lokal koordinat sistemine de uygulanır ve kutumuzun sağ yüzeyi halen lokal Z eksenine bakar. Bu durumda, tüm bu hareketlerden sonra kutunun sağ yüzeyine doğru hareket etmesi için yapmamız gereken tek şey, lokal Z ekseni boyunca koordinat değerini arttırmaktır, hepsi bu kadar. Bırakalım, trigonometri ile de matematik mühendisleri uğraşsın, değil mi :)

İşin aslı, lokal ve global koordinat sistemleri arasındaki geçiş, yukarıda bahsettiğim kadar basit değildir. Eğer bu işi Three.JS gibi hazır bir kütüphane ile yapıyor olmasaydık, burada matris dönüşümlerini anlatmak zorunda kalırdım. Ancak sağ olsunlar, bu işi bize oldukça kolaylaştırmışlar.

Pekala, bu kadar teorik bilgi yeter. Haydi, iş başına. İlk olarak HTML belgemizi hazırlayalım.

<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1254" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="three-r61.min.js"></script>
<script src="program.js"></script>
</head>
<body>
</body>
</html>

Ardından "program.js" dosyamızı hazırlayalım.

"use strict";

var renderer, scene, camera, box, pressedKeys = {};

var keyCodes = { W: 87, S: 83, A: 65, D: 68, Q: 81, E: 69 };

$(document).ready(function () {

    addContainer();

    setStyle();

    prepareScene();

    keyBinding();

    addBox();

    animation();

});

function addContainer() {

    $("body").append("
<br>"); } function setStyle() { $("html, body, #Container").css("width", "100%"); $("html, body, #Container").css("height", "100%"); $("html, body, #Container").css("padding", "0"); $("html, body, #Container").css("margin", "0"); $("html, body, #Container").css("overflow", "hidden"); $("html, body, #Container").css("backgroundColor", "#000000"); } function prepareScene() { var container = $("#Container"); renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(container.width(), container.height()); container.append(renderer.domElement); scene = new THREE.Scene(); var aspectRatio = container.width() / container.height(); camera = new THREE.PerspectiveCamera(45, aspectRatio, 0.1, 20000); camera.position.set(50, 70, 300); var ambientLight = new THREE.HemisphereLight(0xffffff, 0x222222, 0.9); scene.add(ambientLight); } function keyBinding() { $(document).keydown(function (e) { pressedKeys[e.which] = true; }); $(document).keyup(function (e) { delete pressedKeys[e.which]; }); } function addBox() { box = new THREE.Mesh(new THREE.CubeGeometry(20, 20, 20), new THREE.MeshLambertMaterial({ color: 0xff0000 })); scene.add(box); } function animation() { moveBox(); renderer.render(scene, camera); requestAnimationFrame(animation); } function moveBox() { if (pressedKeys[keyCodes.W]) { box.translateZ(-1); } if (pressedKeys[keyCodes.S]) { box.translateZ(1); } if (pressedKeys[keyCodes.A]) { box.rotation.y += 0.05; } if (pressedKeys[keyCodes.D]) { box.rotation.y -= 0.05; } if (pressedKeys[keyCodes.Q]) { box.rotation.x -= 0.05; } if (pressedKeys[keyCodes.E]) { box.rotation.x += 0.05; } }


Bu örneğin hazır yazılmışını çalıştırmak için buraya tıklayabilirsin. Karşına aşağıdaki gibi bir sayfanın gelmesi gerekiyor.


Kodun büyük çoğunluğu, bir önceki makalede bulunan son örneğe benziyor. Yine klavyedeki 6 tuşu bir değişkende tutuyoruz ve tuşların durumlarına göre "animation" fonksiyonu içerisinde kutunun sahnedeki duruşunu değiştiriyoruz. Peki farklı neler var, onlara bakalım.

    if (pressedKeys[keyCodes.A]) {
        box.rotation.y += 0.05;
    }

    if (pressedKeys[keyCodes.D]) {
        box.rotation.y -= 0.05;
    }

    if (pressedKeys[keyCodes.Q]) {
        box.rotation.x -= 0.05;
    }

    if (pressedKeys[keyCodes.E]) {
        box.rotation.x += 0.05;
    }

İlk farkımız, artık A-D-Q-E tuşlarına bastığımızda, kutunun pozisyonunu değiştirmiyoruz. Bunun yerine y ve x eksenleri etrafında dönmesini sağlıyoruz. Güzel, buraya kadar bilmediğimiz bir şey yok.

Peki asıl istediğimiz neydi? Kutunun bir önü var. Biz istiyoruz ki, W tuşuna bastığımızda kutu, önü ne taraftaysa o tarafa doğru gitsin. Aynı şekilde S tuşuna bastığımızda kutu, arkası ne taraftaysa o tarafa doğru gitsin.  Bu bağlamda, kutunun lokal koordinat sisteminde ön tarafı -Z, arka tarafı da +Z olarak kabullenmiş olalım. Artık ileri gitmesi için söylememiz gereken tek şey, lokal Z koordinat değerini azalt olmalı. Bunu da şu şekilde söylüyoruz.

    if (pressedKeys[keyCodes.W]) {
        box.translateZ(-1);
    }

Buradaki "translateZ" fonksiyonu, bizim için dış koordinat-iç koordinat sistemi dönüşümünü yapıyor. Benzer şekilde geri gitmesi için kullanmamız gereken kod dizimi de şu şekilde oluyor.

    if (pressedKeys[keyCodes.S]) {
        box.translateZ(1);
    }

Hepsi bu kadar. Bunun üzerine, kutumuzu ne tarafa döndürürsek döndürelim, ön yüzü olarak kabullendiğimiz yüzünün olduğu tarafa doğru gitmeye devam edecektir. Elbette ileride trigonometriye ihtiyacımızın olacağı durumlar çıkacaktır ama şimdilik yırttık diyebiliriz :)

Makaleyi sonlandırırken öğrendiklerimizi özetleyelim.
  • Sahneye yerleştirilen her bir nesne için global ve lokal koordinat sistemi mevcuttur (Bazen bunları world space ve object space olarak da duyabilirsin).
  • Global koordinat sistemi, herhangi bir nesneye bağımlı kalmaksızın mutlak şekilde sabit kalır.
  • Lokal koordinat sistemi, nesneye uygulanan transformasyonlarla birlikte aynı şekilde değişikliğe uğrar.
  • Sahnedeki nesneleri lokal koordinat sistemi ile hareket ettirmek, çoğu durum için daha kolaydır.
  • Nesneleri lokal koordinat sistemi üzerinden konumlandırmak için "translateX", "translateY" ve "translateZ" fonksiyonları kullanılır.


Yorum Gönder

  1. Merhaba ,Biz three.js kullanarak 3 boyutlu bir yarış oyunu yapıyoruz.Oyun web üzerinde olacak grafik olarak bir yol tasarladık. yolda bir küb gezdireceğiz. Ama bu küb yoldan cıkmayacak ve kenar hassasiyeti olacak.(physijs veya ammo.js kütüphanesi kullanmalıyız sanırım.)Bunu nasıl yapabiliriz. Kamera olarak perspective camera kullanıyoruz.Nasıl yapacağımız hakkında en ufak fikrimiz yok..Nasıl yapabiliriz.yardımcı olursanız cok seviniriz.İyi günler.

    YanıtlaSil

 
Top