3B efektler için üçgenleri kullanma

Flash Player 10 ve üstü, Adobe AIR 1.5 ve üstü

3B modeller, üçgenlerin bir alanda toplanmasıyla temsil edildiği için ActionScript'te Graphics.drawTriangles() yöntemini kullanarak bitmap dönüşümleri yapabilirsiniz. (Ancak, Flash Player ve AIR uygulaması derinlik arabelleğini desteklemez, bu nedenle görüntüleme nesneleri doğası gereği yassı veya 2B olmaya devam eder. Bu, Flash Player ve AIR çalışma zamanında 3B görüntüleme nesnelerini anlama bölümünde bu açıklanmaktadır.) Graphics.drawTriangles() yöntemi, bir üçgen yolu çizmek için koordinatlar kümesini aldığından, Graphics.drawPath() yöntemine benzer.

Graphics.drawPath() öğesini kullanmaya alışmak için, bkz. Yol Çizme .

Graphics.drawTriangles() yöntemi, üçgen yolu için nokta konumlarını belirtmek üzere bir Vector.<Number> öğesi kullanır:

drawTriangles(vertices:Vector.<Number>, indices:Vector.<int> = null, uvtData:Vector.<Number> = null, culling:String = "none"):void

drawTriangles() öğesinin birinci parametresi 8 vertices parametresi), zorunlu olan tek parametredir. Bu parametre, üçgenlerinizin çizildiği koordinatları tanımlayan sayıların bir vektörüdür. Her üç koordinat kümesi (altı sayı) bir üçgen yolunu temsil eder. Her üçgen üç koordinat çifti (üç tane x/y değerleri kümesi) gerektirdiğinden, indices parametresi olmadan, vektör uzunluğu her zaman altının bir faktörü olmalıdır. Örneğin:

graphics.beginFill(0xFF8000); 
graphics.drawTriangles( 
    Vector.<Number>([ 
        10,10,  100,10,  10,100, 
        110,10, 110,100, 20,100]));

Bu üçgenlerin hiçbiri bir nokta paylaşmaz ancak paylaşsalardı, birden çok üçgen için vertices vektöründe değerleri yeniden kullanmak üzere ikinci drawTriangles() parametresi olan indices kullanılabilirdi.

indices parametresini kullanırken, indices değerlerinin doğrudan vertices dizi öğeleriyle ilgili olan dizinler değil, nokta dizinleri olmasına dikkat edin. Başka bir deyişle, indices tarafından tanımlandığı şekilde vertices vektöründeki bir dizin gerçekte 2'ye bölünen gerçek dizindir. vertices vektörünün üçüncü noktası için, söz konusu noktanın birinci sayısal değeri 4 vektör dizininde başlasa da, örneğin indices değeri olarak 2'yi kullanın.

Örneğin, indices parametresini kullanarak çapraz kenarı paylaşacak şekilde iki üçgeni birleştirin:

graphics.beginFill(0xFF8000); 
graphics.drawTriangles( 
    Vector.<Number>([10,10, 100,10, 10,100, 100,100]), 
    Vector.<int>([0,1,2, 1,3,2]));

Şimdi iki üçgen kullanılarak bir kare çizilmiş olsa da, vertices vektöründe yalnızca dört noktanın belirtilmiş olduğuna dikkat edin. indices öğesi kullanılarak, iki üçgen tarafından paylaşılan iki nokta, her üçgen için yeniden kullanılır. Bu da, genel kesişme noktaları sayısını 6'dan (12 sayı) 4'e (8 sayı) düşürür:

vertices parametresi kullanılarak iki üçgenle çizilmiş bir kare

Bu teknik, çoğu noktanın birden çok üçgen tarafından paylaşıldığı daha büyük üçgen kafesleri için kullanışlıdır.

Üçgenlere tüm dolgular uygulanabilir. Dolgular, diğer şekillere olduğu gibi sonuçta elde edilen üçgene de uygulanır.

Bitmap'leri dönüştürme

Bitmap dönüştürmeleri, üç boyutlu bir nesne üzerinde perspektif veya "doku" görünümü sağlar. Özel olarak, görüntünün ufuk noktasına yaklaştıkça daralıyor gibi görünmesi için ufuk noktasına doğru bir bitmap'i deforme edebilirsiniz. Veya, üç boyutlu bir nesneye için yüzey oluşturmak üzere iki boyutlu bitmap kullanarak o üç boyutlu nesne üzerinde doku veya "sargı" görünümü sağlayabilirsiniz.

Bir ufuk noktası ve bitmap ile sarılmış üç boyutlu bir nesne kullanan iki boyutlu yüzey.

UV eşleme

Dokularla çalışmaya başladıktan sonra drawTriangles() öğesinin uvtData parametresinden yararlanmak istersiniz. Bu parametre, bitmap dolgular için UV eşleme ayarlamanıza olanak sağlar.

UV eşleme, nesneleri dokulaştırma yöntemidir. Bu iki değeri esas alır: U yatay (x) değeri ve V dikey (y) değeri. Bunlar piksel değerlerini değil, yüzdeleri esas alır. 0 U ve 0 V, görüntünün sol üst kısmı iken, 1 U ve 1 V de görüntünün sağ alt kısmıdır:

Bitmap görüntüde UV 0 ve 1 konumları

Üçgen vektörlerinin bir görüntüdeki ilgili konumlarla ilişkilendirilmesi için söz konusu üçgen vektörlerine UV koordinatları verilebilir:

Bitmap görüntünün üçgen alanının UV koordinatları

UV değerleri, üçgenin noktalarıyla tutarlı kalır:

Üçgenin kesişme noktaları hareket eder ve bitmap, tek bir noktanın UV değerlerini aynı tutmak için deforme olur

ActionScript 3B dönüştürmeler, bitmap'le ilişkilendirilmiş üçgene uygulanırken, bitmap görüntü, UV değerlerini esas alan üçgene uygulanır. Bu nedenle, matris hesaplamalarını kullanmak yerine, üç boyutlu efektler oluşturmak için UV değerlerini ayarlayın.

Graphics.drawTriangles() yöntemi ayrıca üç boyutlu dönüştürmeler için isteğe bağlı bir bilgiyi de kabul eder: T değeri. uvtData öğesindeki T değeri, 3B perspektifi veya daha net olmak gerekirse, ilişkilendirilmiş tepenin ölçek faktörünü temsil eder. UVT eşleme, UV eşlemeye perspektif düzeltmesi ekler. Örneğin, bir nesne, 3B alanda "orijinal" boyutunun %50'si kadar görünecek şekilde görüş açısından uzağa konumlandırılırsa, o nesnenin T değeri 0,5 olur. 3B alanda nesneleri temsil etmek için üçgenler çizildiğinden, bunların z ekseni boyunca konumları T değerlerini belirler. T değerini belirleyen eşitlik şöyledir:

T = focalLength/(focalLength + z);
Bu eşitlikte, focalLength bir odak uzaklığını veya görünümde sağlanan perspektif miktarını dikte eden hesaplanmış "ekran" konumunu temsil eder.
Odak uzaklığı ve z değeri
A.
görüş açısı

B.
ekran

C.
3B nesne

D.
focalLength değeri

E.
z değeri

Temel şekilleri daha uzak mesafede görünecek şekilde ölçeklemek için T değeri kullanılır. Bu genellikle 3B noktaları 2B noktalara dönüştürmek için kullanılan değerdir. UVT verileri olması durumunda, perspektif içeren bir üçgen içindeki noktalar arasında bitmap'i ölçeklemek için de bu kullanılır.

UVT değerlerini tanımladığınızda, T değeri doğrudan tepe için tanımlanan UV değerlerini izler. T'nin eklenmesiyle, uvtData parametresindeki her üç değer (U, V ve T), vertices parametresindeki her iki değerle (x ve y) eşleştirilir. UV değerleri tek olduğunda, uvtData.length == vertices.length. T değeri eklendiğinde, uvtData.length = 1.5*vertices.length.

Şu örnek, UVT verileri kullanılarak 3B alanda döndürülen bir düzlemi gösterir. Bu örnek, BitmapData nesnesine atanabilmesi için ocean.jpg görüntüsünü yüklemek üzere ocean.jpg adında bir görüntüyü ve ImageLoader adında bir “yardımcı” sınıfı kullanır.

Burada ImageLoader sınıf kaynağı verilmiştir (bu kodu ImageLoader.as adındaki bir dosyaya kaydedin):

package { 
    import flash.display.* 
    import flash.events.*; 
    import flash.net.URLRequest; 
    public class ImageLoader extends Sprite { 
        public var url:String; 
        public var bitmap:Bitmap; 
    public function ImageLoader(loc:String = null) { 
        if (loc != null){ 
            url = loc; 
            loadImage(); 
        } 
    } 
    public function loadImage():void{ 
        if (url != null){ 
            var loader:Loader = new Loader(); 
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete); 
            loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIoError); 
             
                var req:URLRequest = new URLRequest(url); 
                loader.load(req); 
            } 
        } 
         
    private function onComplete(event:Event):void { 
            var loader:Loader = Loader(event.target.loader); 
            var info:LoaderInfo = LoaderInfo(loader.contentLoaderInfo); 
            this.bitmap = info.content as Bitmap; 
            this.dispatchEvent(new Event(Event.COMPLETE)); 
    } 
         
    private function onIoError(event:IOErrorEvent):void { 
            trace("onIoError: " + event); 
    } 
    } 
}

Burada da görüntünün bir ufuk noktasına doğru daralıyor ve dönüyor gibi görünmesini sağlamak için üçgenleri, UV eşlemeyi ve T değerlerini kullanan ActionScript verilmiştir. Bu kodu Spinning3dOcean.as adındaki bir dosyaya kaydedin:

package { 
    import flash.display.* 
    import flash.events.*; 
    import flash.utils.getTimer; 
     
    public class Spinning3dOcean extends Sprite { 
        // plane vertex coordinates (and t values) 
        var x1:Number = -100,    y1:Number = -100,    z1:Number = 0,    t1:Number = 0; 
        var x2:Number = 100,    y2:Number = -100,    z2:Number = 0,    t2:Number = 0; 
        var x3:Number = 100,    y3:Number = 100,    z3:Number = 0,    t3:Number = 0; 
        var x4:Number = -100,    y4:Number = 100,    z4:Number = 0,    t4:Number = 0; 
        var focalLength:Number = 200;      
        // 2 triangles for 1 plane, indices will always be the same 
        var indices:Vector.<int>; 
         
        var container:Sprite; 
         
        var bitmapData:BitmapData; // texture 
        var imageLoader:ImageLoader; 
        public function Spinning3dOcean():void { 
            indices =  new Vector.<int>(); 
            indices.push(0,1,3, 1,2,3); 
             
            container = new Sprite(); // container to draw triangles in 
            container.x = 200; 
            container.y = 200; 
            addChild(container); 
             
            imageLoader = new ImageLoader("ocean.jpg"); 
            imageLoader.addEventListener(Event.COMPLETE, onImageLoaded); 
        } 
        function onImageLoaded(event:Event):void { 
            bitmapData = imageLoader.bitmap.bitmapData; 
            // animate every frame 
            addEventListener(Event.ENTER_FRAME, rotatePlane); 
        } 
        function rotatePlane(event:Event):void { 
            // rotate vertices over time 
            var ticker = getTimer()/400; 
            z2 = z3 = -(z1 = z4 = 100*Math.sin(ticker)); 
            x2 = x3 = -(x1 = x4 = 100*Math.cos(ticker)); 
             
            // calculate t values 
            t1 = focalLength/(focalLength + z1); 
            t2 = focalLength/(focalLength + z2); 
            t3 = focalLength/(focalLength + z3); 
            t4 = focalLength/(focalLength + z4); 
             
            // determine triangle vertices based on t values 
            var vertices:Vector.<Number> = new Vector.<Number>(); 
            vertices.push(x1*t1,y1*t1, x2*t2,y2*t2, x3*t3,y3*t3, x4*t4,y4*t4); 
            // set T values allowing perspective to change 
            // as each vertex moves around in z space 
            var uvtData:Vector.<Number> = new Vector.<Number>(); 
            uvtData.push(0,0,t1, 1,0,t2, 1,1,t3, 0,1,t4); 
             
            // draw 
            container.graphics.clear(); 
            container.graphics.beginBitmapFill(bitmapData); 
            container.graphics.drawTriangles(vertices, indices, uvtData); 
        } 
    } 
}

Bu örneği test etmek için, bu iki sınıf dosyasını “ocean.jpg” adındaki bir görüntüyle aynı dizine kaydedin. Orijinal bitmap'in, 3B alanda gittikçe kayboluyor ve dönüyor gibi görünmesi için nasıl dönüştürüldüğünü görebilirsiniz.

Yüzey kaldırma

Yüzey kaldırma, geçerli görüş açısından gizlendikleri için oluşturucunun, üç boyutlu bir nesnenin hangi yüzeylerini oluşturmaması gerektiğini belirleyen işlemdir. 3B alanda, üç boyutlu nesnenin "arkasındaki" yüzey, görüş açısından gizlenir:
3B nesnenin arkası, görüş açısından gizlenir.
A.
görüş açısı

B.
3B nesne

C.
üç boyutlu nesnenin arkası

Doğası gereği tüm üçgenler, boyutu, şekli veya konumuna bakılmaksızın her zaman oluşturulur. Yüzey kaldırma, Flash Player veya AIR uygulamasının 3B nesnenizi doğru şekilde oluşturmasını sağlar. Ayrıca daire oluşturma işlemini azaltmak için bazen oluşturucu tarafından bazı üçgenlerin atlanmasını istersiniz. Alanda dönen bir küpü göz önünde bulundurun. Görüş açısı içinde olmayan kenarlar, küpün diğer tarafındaki diğer yöne baktığından, asla o küpün üç kenarından fazlasını görmezsiniz. Bu kenarlar görünmeyeceğinden, oluşturucunun bunları çizmemesi gerekir. Yüzey kaldırma olmadan, Flash Player veya AIR uygulaması hem ön hem de arka kenarları oluşturur.

Küpte ise geçerli görüş açısından görünmeyen kenarlar vardır

Bu nedenle, Graphics.drawTriangles() yöntemi, yüzey kaldırma değeri oluşturmak için dördüncü bir parametre içerir:

public function drawTriangles(vertices:Vector.<Number>, indices:Vector.<int> = null, uvtData:Vector.<Number> = null, culling:String = "none"):void

culling parametresi, TriangleCulling numaralandırma sınıfındaki bir değerdir: TriangleCulling.NONE , TriangleCulling.POSITIVE ve TriangleCulling.NEGATIVE . Bu değerler, nesnenin yüzeyini tanımlayan üçgen yolunun yönüne bağlıdır. Yüzey kaldırmanın belirlenmesine yönelik ActionScript API'si, 3B şeklin tüm dışarı bakan üçgenlerinin aynı yol yönünde çizildiğini varsayar. Üçgenin bir yüzü ters döndüğünde, yol yönü de değişir. Bu noktada, üçgenin yüzeyi kaldırılabilir. (Oluşturma işleminden çıkarılır.)

Böylece, POSITIVE öğesinin bir TriangleCulling değeri, pozitif yol yönüne (saat yönüne) sahip üçgenleri kaldırır. NEGATIVE öğesinin TriangleCulling değeri, negatif (saat yönünün tersi) yol yönüne sahip üçgenleri kaldırır. Küp olması durumunda, öne bakan yüzeyler pozitif yol yönüne sahip olurken, arkaya bakan yüzeyler negatif yol yönüne sahip olur:

Yol yönünü göstermek için "sarılmamış" bir küp. "Sarılmadığında", arka taraftaki yol yönü ters çevrilir.

Yüzey kaldırmanın nasıl çalıştığını görmek için, UV eşleme bölümündeki önceki örnekle başlayın, drawTriangles() yönteminin culling parametresini TriangleCulling.NEGATIVE olarak ayarlayın:

container.graphics.drawTriangles(vertices, indices, uvtData, TriangleCulling.NEGATIVE);

Görüntünün "arka" tarafının nesne döndükçe oluşturulmadığını göreceksiniz.