Programming Forums

Programming Forums (http://www.programmingforums.org/forumindex.php)
-   Other Scripting Languages (http://www.programmingforums.org/forum39.html)
-   -   Matrix Math in ActionScript 2.0 (http://www.programmingforums.org/showthread.php?t=10069)

grimpirate May 30th, 2006 12:54 AM

Matrix Math in ActionScript 2.0
 
Don't know if this will be of any help to anyone but I've been working on creating a very simplistic 3d engine in Flash, and so it was necessary to figure out how to do some matrix operations. Hope these help anyone whose had a similar problem. Some functions build on the others so, be careful of using one without the others.
:

// Computes the Inverse of a matrix
function inverse(A):Array{
        var Ainv, E, i, j, k, n, swap;
        n = A.length;
        Ainv = identity(n);
        E = identity(n);
        for(j = 0; j < n; j++){
                for(i = j; i < n; i++){
                        if(i == j){
                                if(A[i][j] == 0){
                                        for(k = j + 1; k < n; k++){
                                                if(A[k][j] != 0){
                                                        swap = A[i];
                                                        A[i] = A[k];
                                                        A[k] = swap;
                                                        swap = Ainv[i];
                                                        Ainv[i] = Ainv[k];
                                                        Ainv[k] = swap;
                                                        k = n;
                                                }
                                        }
                                }
                                E[i][j] = 1 / A[i][j];
                        }else{
                                E[i][j] = -A[i][j];
                        }
                        A = multiply(E, A);
                        Ainv = multiply(E, Ainv);
                        E = identity(n);
                }
        }
        for(j = n - 1; j > 0; j--){
                for(i = j - 1; i > -1; i--){
                        E[i][j] = -A[i][j];
                        A = multiply(E, A);
                        Ainv = multiply(E, Ainv);
                        E = identity(n);
                }
        }
        return Ainv;
}

// Multiplies two matrices together by making use of the Dot Product
function multiply(A, B):Array{
        var M, i, j;
        B = transpose(B);
        M = new Array(A.length);
        for(i = 0; i < M.length; i++){
                M[i] = new Array(B.length);
        }
        for(i = 0; i < A.length; i++){
                for(j = 0; j < B.length; j++){
                        M[i][j] = dotProduct([A[i]],[B[j]]);
                }
        }
        return M;
}

// Calculate the Transpose of a matrix
// Takes matrices of any type so long as they're enclosed in double brackets
// I.E. [[]] This applies to 1 x 1 matrices as well as row and column vectors
function transpose(A):Array{
        var T, i, j;
        T = new Array(A[0].length);
        for(i = 0; i < T.length; i++){
                T[i] = new Array(A.length);
        }
        for(i = 0; i < A.length; i++){
                for(j = 0; j < A[0].length; j++){
                        T[j][i] = A[i][j];
                }
        }
        return T;
}

// Calculate the Dot Product of two vectors
// Takes two row vectors of the form [[,,,...]]
// OR column vectors of the form [[],[],...]
function dotProduct(a, b):Number{
        var product = 0;
        var i, j;
        if(a.length == 1){
                for(j = 0; j < a[0].length; j++){
                        product += a[0][j] * b[0][j];
                }
        }else{
                for(i = 0; i < a.length; i++){
                        product += a[i][0] * b[i][0];
                }
        }
        return product;
}

// Returns an identity matrix of Nth size
function identity(n):Array{
        var A, i, j;
        A = new Array(n);
        for(i = 0; i < n; i++){
                A[i] = new Array(n);
        }
        for(i = 0; i < n; i++){
                for(j = 0; j < n; j++){
                        if(i == j){
                                A[i][j] = 1;
                        }else{
                                A[i][j] = 0;
                        }
                }
        }
        return A;
}

If it so happens that the 3d engine works and I have any other useful matrix functions, I'll post them here. Need any explanations of the code just ask your questions and I'd be happy to answer.

grimpirate May 30th, 2006 10:06 PM

Any ideas why this isn't working?
 
1 Attachment(s)
I've encountered a problem which makes no sense to me. I created the the 8 vertexes for a cube, and sure enough I transformed them into a 2d plane. But for some reason the place where I stored by vertexes, the array called 'cube' is being edited when I'm not performing any sort of arithmetic on it. Can someone suggest why this is happening? I included my source '.fla' file for Macromedia Flash MX if anyone happens to have it but I'll also place it here. If you can look over and tell me why the vertex cube[0] changes when it shouldn't I'd appreciate it.

This ActionScript code is on Frame 1 of Layer 1 in the project:
:

var cube = [[[50],[50],[50],[0]],
                        [[-50],[50],[50],[0]],
                        [[50],[-50],[50],[0]],
                        [[-50],[-50],[50],[0]],
                        [[50],[50],[-50],[0]],
                        [[-50],[50],[-50],[0]],
                        [[50],[-50],[-50],[0]],
                        [[-50],[-50],[-50],[0]]];

// Computes the Inverse of a matrix
function inverse(A):Array{
        var Ainv, E, i, j, k, n, swap;
        n = A.length;
        Ainv = identity(n);
        E = identity(n);
        for(j = 0; j < n; j++){
                for(i = j; i < n; i++){
                        if(i == j){
                                if(A[i][j] == 0){
                                        for(k = j + 1; k < n; k++){
                                                if(A[k][j] != 0){
                                                        swap = A[i];
                                                        A[i] = A[k];
                                                        A[k] = swap;
                                                        swap = Ainv[i];
                                                        Ainv[i] = Ainv[k];
                                                        Ainv[k] = swap;
                                                        k = n;
                                                }
                                        }
                                }
                                E[i][j] = 1 / A[i][j];
                        }else{
                                E[i][j] = -A[i][j];
                        }
                        A = multiply(E, A);
                        Ainv = multiply(E, Ainv);
                        E = identity(n);
                }
        }
        for(j = n - 1; j > 0; j--){
                for(i = j - 1; i > -1; i--){
                        E[i][j] = -A[i][j];
                        A = multiply(E, A);
                        Ainv = multiply(E, Ainv);
                        E = identity(n);
                }
        }
        return Ainv;
}

// Multiplies two matrices together by making use of the Dot Product
function multiply(A, B):Array{
        var M, i, j;
        B = transpose(B);
        M = new Array(A.length);
        for(i = 0; i < M.length; i++){
                M[i] = new Array(B.length);
        }
        for(i = 0; i < A.length; i++){
                for(j = 0; j < B.length; j++){
                        M[i][j] = dotProduct([A[i]],[B[j]]);
                }
        }
        return M;
}

// Calculate the Transpose of a matrix
// Takes matrices of any type so long as they're enclosed in double brackets
// I.E. [[]] This applies to 1 x 1 matrices as well as row and column vectors
function transpose(A):Array{
        var T, i, j;
        T = new Array(A[0].length);
        for(i = 0; i < T.length; i++){
                T[i] = new Array(A.length);
        }
        for(i = 0; i < A.length; i++){
                for(j = 0; j < A[0].length; j++){
                        T[j][i] = A[i][j];
                }
        }
        return T;
}

// Calculate the Dot Product of two vectors
// Takes two row vectors of the form [[,,,...]]
// OR column vectors of the form [[],[],...]
function dotProduct(a, b):Number{
        var product = 0;
        var i, j;
        if(a.length == 1){
                for(j = 0; j < a[0].length; j++){
                        product += a[0][j] * b[0][j];
                }
        }else{
                for(i = 0; i < a.length; i++){
                        product += a[i][0] * b[i][0];
                }
        }
        return product;
}

// Calculates the magnitude of a vector
// Takes two row vectors of the form [[,,,...]]
// OR column vectors of the form [[],[],...]
function magnitude(a):Number{
        var mag = 0;
        var i, j;
        if(a.length == 1){
                for(j = 0; j < a[0].length; j++){
                        mag += Math.pow(a[0][j], 2);
                }
                mag = Math.sqrt(mag);
        }else{
                for(i = 0; i < a.length; i++){
                        mag += Math.pow(a[i][0], 2);
                }
                mag = Math.sqrt(mag);
        }
        return mag;
}

// Returns an identity matrix of Nth size
function identity(n):Array{
        var A, i, j;
        A = new Array(n);
        for(i = 0; i < n; i++){
                A[i] = new Array(n);
        }
        for(i = 0; i < n; i++){
                for(j = 0; j < n; j++){
                        if(i == j){
                                A[i][j] = 1;
                        }else{
                                A[i][j] = 0;
                        }
                }
        }
        return A;
}

The following code is attached to a button that is on the scene:
:

on(press){
        output_txt.text = "";
        x = Math.sqrt(2)/2;
        focal = 100;
        plane = createEmptyMovieClip("Scene", 1);
        plane.clear();
        plane.lineStyle(1, "0x000000", 100);
        g = [[-x,0.5,-0.5,0],[x,0.5,-0.5,0],[0,-x,-x,0],[0,0,0,1]];
        g = inverse(g);
        g[0][3] = 150;
        g[1][3] = 150;
        g[2][3] = 300*x;
       
        h = cube[0];
        output_txt.text += cube[0] + "\n\n";
        for(i = 0; i < h.length - 1; i++){
                h[i][0] -= g[i][g.length - 1];
        }
        h = multiply(g,h);
        distance = magnitude(h);
        x = 300 + (focal * h[0][0] / distance);
        y = 200 + (focal * h[1][0] / distance);
        plane.moveTo(x, y);
       
        h = cube[1];
        output_txt.text += cube[0] + "\n\n";
        for(i = 0; i < h.length - 1; i++){
                h[i][0] -= g[i][g.length - 1];
        }
        h = multiply(g,h);
        distance = magnitude(h);
        x = 300 + (focal * h[0][0] / distance);
        y = 200 + (focal * h[1][0] / distance);
        plane.lineTo(x, y);
       
        h = cube[0];
        output_txt.text += cube[0] + "\n\n";
        for(i = 0; i < h.length - 1; i++){
                h[i][0] -= g[i][g.length - 1];
        }
        h = multiply(g,h);
        distance = magnitude(h);
        x = 300 + (focal * h[0][0] / distance);
        y = 200 + (focal * h[1][0] / distance);
        plane.lineTo(x, y);
}

That's all the code there is, on the stage is a dynamic text field called 'output_txt' and a button to which the previous code is attached. The button code makes the transformations from 3d to 2d of the vertexes and the draws them. Frame 1 just holds the functions for matrix manipulation and the coordinates of the cubes vertexes.

The problem: I draw a line from vertex 0 to vertex 1 and then back to vertex 0. However, the lines don't trace exactly over one another. The second line actually ends up higher than the first, such that they're offset by an angle. This shouldn't be happening. And as you can see any time I used the cube array it's always on the right hand side of an assignment statement.

What's going on here? Why are my vertices being edited when I don't think I'm editing them in any way?

grimpirate May 30th, 2006 10:18 PM

Graphical Illustration
 
1 Attachment(s)
I'm enclosing what the output looks like just to further the understanding of it. Also, I apologize for my improper spelling it's vertices not vertexes, and for my lack of y's at the end of many a 'they' as well as improper grammar. Too much math, not enough english while doing this. -_-

The first value in those text fields is the actual coordinate of vertex 0 and the second two are what it's changed to during the drawing sequence.

The lines are what get drawn, and as you can see they're offset.


All times are GMT -5. The time now is 7:57 AM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC