What's new

Melee Arcive Viewer (MAV) in development project.

OP
Tcll

Tcll

Complexity == Fun >:3
well... I got mine importing more faces correctly...
but IDK how to end the face conversion, so it still converts the contained textures into faces...
creating a jumbled mess of faces...
you can still make out the model faces and there are alot more of them...

and Milun...
as I stated before

that code you ignored belongs to a differant face offset
so instead, try reading it like this:
06 46
06 47 |
06 48 |
06 3A |
06 48
06 3B |
06 48 |
06 3C |
06 48
06 3E |

notice how everything is used...
the lines belong to the 2nd groupe of faces
and that purple # is skipped in the first groupe, but read in the 2nd.

anyways, that's my theory...
I havn't had a chance to test it out yet, because my awsomly powerful brain has yet to think of a way to do this... DX<
 
Last edited:

revel8n

New member
Triangle strips often include duplicate indices to allow for creating longer strips of triangles.

Also remember to use the index count available at the beginning of the strip right after the byte that represents the primitive type. If you want to make sure you have a valid set of indices for a triangle just makes sure none of the indices are the same (may also be able to check for invalid values, like values that are out of the range of the number of vertices).

Code:
// 98 00 08
// 0x98 0x0008
int primitiveType = 0x98; // triangle strip
int indexCount = 0x0008;
int triIndices[3] = {0};

int iIndex = 0;
// loop for each index
for (iIndex = 0; iIndex < indexCount; ++iIndex)
{
    triIndex[2] = readIndex();

    // ensure we have the correct number of indices
    if (iIndex >= 2)
    {
        // ensure indices are valid
        if (triIndex[0] != triIndex[1] &&
            triIndex[1] != triIndex[2] &&
            triIndex[2] != triIndex[0])
        {
            fprintf(fp, "f %d %d %d\n", triIndex[0], triIndex[1], triIndex[2]);
        }
    }

    // move last two indices for next triangle
    triIndex[0] = triIndex[1];
    triIndex[1] = triIndex[2];
}

Just an example for interpreting a triangle strip. And you can keep doing that as long as the primitive type and index count are valid. Use the things i described before about the valid primitive types to verify whether or not you should continue.

You should be able to look at some of the code from the Metroid Prime project linked in another thread if you want an example.
 
Last edited:

Milun

New member
Hm... well my trial run with the hex shows that there may still be some faces we're missing. But (although I haven't tried it), I'll bet that if we were to move yet another row down, we'd get the lost faces. Here's what I got so far (left is the raw export, right is the edited with face gibberish removed):

 
OP
Tcll

Tcll

Complexity == Fun >:3
hmm... Revel8n...
could I maybe get your code??

I am very bad at deciphering bits and pieces of C++ :(
and I'm too lazy/busy to go around reading and looking for code...

sorry if this makes you go DX< or D:>
 
Last edited:
OP
Tcll

Tcll

Complexity == Fun >:3
hey Milun...
here's a new theory off of my old theory:

try decompressing the values before converting.
ex:
06 46
06 47 |
06 48 |
06 3A |
06 48
06 3B |
06 48 |
06 3C |
06 48
06 3E |
instead of interpreting the values as this...
they would decompress to:
06 46
06 47
06 48
06 47
06 48
06 3A
06 3A
06 48
06 3B
06 3B
06 48
06 3C
06 3C
06 48
06 3E
06 3E
...
and then interpreted.

try that and see how that works...

EDIT: I got my program doing this, but it "DNA-Converts" the entire file from the current offset...
yes, I'm calling this DNA-Converting =]
 
Last edited:

Milun

New member
Well, I was right, moving one more row down gives the final face data:



Once again though, this still had bit of face gibberish, the picture is of the edited version.
 
OP
Tcll

Tcll

Complexity == Fun >:3
awsome!!:bouncy:

can I get a copy your program??
and please include the source...

I can't really think of a way to get my idea working right... at the moment...

EDIT:
how do you get the index value??
as of right now, my guess would be:
hex2dec(indexcount) = offset
would that be right?
 
Last edited:
OP
Tcll

Tcll

Complexity == Fun >:3
Here is a working version of my DNA-Converter:
Code:
dat = open("import.dat", 'rb')#import dat
tmp = open("hex faces.txt", 'w')#export DNA faces to "faces.txt"
a = 1
while (a == 1):
    h = dat.read(1).encode('hex')+dat.read(1).encode('hex')
    if (h == '9'+h[1]+'00'):
        a = 2
        i = dat.read(1)#.encode('hex')#index count
        while (a == 2):
            ft1 = dat.read(4).encode('hex')
            ft2 = dat.read(4).encode('hex')
            ft3 = dat.read(4).encode('hex')
            #moved forward by 12
            s = dat.seek(-8,1)#move back by 8
 
            f1 = ft1[0]+ft1[1]+ft1[2]+ft1[3]
            f2 = ft2[0]+ft2[1]+ft2[2]+ft2[3]
            f3 = ft3[0]+ft3[1]+ft3[2]+ft3[3]
 
            if (f1 != f2 and f2 != f3 and f3 != f1):
                #if faces are valad (thanx revel8n)
                tmp.write(f1+"\n"+f2+"\n"+f3+"\n"+"\n")
            if (f3 == ''):#end of file
                tmp.close
it doesn't work perfectly... but it does work right.
 
Last edited:

Milun

New member
Well, it'll take a while for me to get my GM program presentable, and I don't know if it will even help you then, but I will. The issue being that Game Maker has a very different way of importing from files to Python (btw, it's importing with the .txt method). Also, pardon my ignorance, but what did you mean by DNA converter?
 
OP
Tcll

Tcll

Complexity == Fun >:3
Well, it'll take a while for me to get my GM program presentable, and I don't know if it will even help you then, but I will. The issue being that Game Maker has a very different way of importing from files to Python
oh... don't worry about python...
I can traslate C++
I just can't tranlate bits and pieces of it...

(btw, it's importing with the .txt method).
that's ok...
I can simply change that...
it's just a matter of dividing the lines read by 2.

Also, pardon my ignorance, but what did you mean by DNA converter?
lol :D
you ever take Biology class... :)
well you know how DNA works right...

so what this does is convert the dat face code into a "DNA" sequence...
or should I say it converts it to an independant face instead of a linked face.
ex:
06 46
06 47 |
06 48 |
06 3A |
to:
06 46
06 47
06 48
06 47
06 48
06 3A
similar to how DNA works... :)

you could also call it a decompressor...
 
Last edited:

Milun

New member
...oh...

Heh, uh well, the thing about GM is a... it has it's own (relatively primitive) scripting language. The only reason I used it instead of C++, was because I didn't (and still don't) know how to read the hex from a .dat file. I'm working on making it presentable with nice comments now. Just keep in mind, it is in no means complete.

Incidentally, throughout the day I was wondering: how are we going to import custom models back into Melee. I mean, somehow they managed to put each face inside the others. I think I know why they place '98 00' constantly, because it seems to be used whenever they can no longer fit another face in a face...

At the cost of reducing quality a tad, on the importing side we may have to resort to making it:

98 00 47
face point 1
face point 2
face point 3
98 00 47
etc.

At least that way, there are non of the weird overlapping faces. I just think it'll be near impossible to make the program automatically layer faces like Nintendo did.

Also:

 
Last edited:
OP
Tcll

Tcll

Complexity == Fun >:3
...oh...

Heh, uh well, the thing about GM is a... it has it's own (relatively primitive) scripting language. The only reason I used it instead of C++, was because I didn't (and still don't) know how to read the hex from a .dat file. I'm working on making it presentable with nice comments now.

Ahh... I see... so I misunderstood you o_O DX> :(

so basically it's like O3D (Original 3D)...
it has it's own lang, but the prog really sucks, mainly because the dev dude didn't include the docs.
he only included a few models and alot of scripts end expected you to play with them to figure out the code. (FAIL)

I use Py instead of C++ because you dont have to worry about compiling and getting those nagging compile errors that lead you nowhere...

and on reading the hex...
I guess you'd be in the same place as me... :blush:
I should really learn to keep my big mouth shut and stop asking so many Q's :doh: :happy:
well... I guess, send me the code and I'll try to interpret it...
Please include alot of comments, or I might get lost...
 
Last edited:
OP
Tcll

Tcll

Complexity == Fun >:3
and no... not impossible... just extremely hard...

I'd say it's a pretty engenius way of getting the models to take up as little space as possible.
EDIT: while still being readable...
that's also including textures and anything elsethat would go inside it...
let's not forget... it is a compressed archive...

so whatever format they used for the models...
got compressed into this...

I'm also assuming the texture data would have to be in a similar format before it is compressed...

IDK if this will work... but I'd like to try using the hex R G B values on the texture data...
if not "R G B", then it would probably be double layered "R R G G B B"
just a wild guess... I might have it all wrong, but it's worth a try...

anyways... it's 1:00 A.M. over here... so I think I'm gonna call it a night.
got school in the mornin... DX<
 
Last edited:

Milun

New member
Well, it took a while, but here it is:

Code:
//Set default string variable to 'f '
STRINGWRITE = 'f '

//Checks wether the reset hex '98 00' occurs before the face ends (3 x 8), and if so,
//changes offset to the begging of the first face after the offending '98 00 xx'.
TESTSTRING = string_copy(MData,Position,19);
if string_pos('9800',TESTSTRING) != 0 && string_pos('009800',TESTSTRING) == 0 then {Position += string_pos('9800',TESTSTRING)+5;}

//Part of the model convert code, just ignore it. Also, it helps to check if
//the end of the file is reached.

//Also, from here till the next comment, it's just converting the first 4 digits
//from the offset ('Position' variable) from hex to decimal.
Hex = string_copy(MData,Position+1,1);
if Hex == 'Q' then {
file_text_write_string(MWrite,' ');
file_text_close(MWrite);
show_message('Done!');
obj_exportBut.image_index = 0;
obj_importBut.image_index = 0;
instance_destroy();
exit;}
script_execute(scr_Za);
XXX = DigA;
Hex = string_copy(MData,Position+2,1);
script_execute(scr_DigA);
Hex = string_copy(MData,Position+3,1);
script_execute(scr_DigB);
YYY = DigA+DigB+1;
//No more converting, and now variable Face1A to the converted hex.
Face1A = XXX+YYY;

//Now converts the second third of face 1, and makes the first third
//of the face 2 equal the same number.
Hex = string_copy(MData,Position+9,1);
script_execute(scr_Za);
XXX = DigA;
Hex = string_copy(MData,Position+10,1);
script_execute(scr_DigA);
Hex = string_copy(MData,Position+11,1);
script_execute(scr_DigB);
YYY = DigA+DigB+1;

Face1B = XXX+YYY;
Face2A = Face1B;

//Now converts the last third of face 1, and makes the second third
//of the face 2 equal the same number, AND the first third of face 3.
Hex = string_copy(MData,Position+17,1);
script_execute(scr_Za);
XXX = DigA;
Hex = string_copy(MData,Position+18,1);
script_execute(scr_DigA);
Hex = string_copy(MData,Position+19,1);
script_execute(scr_DigB);
YYY = DigA+DigB+1;

Face1C = XXX+YYY;
Face2B = Face1C;
Face3A = Face1C;

//Now converts the last third of face 2, and makes the second third
//of the face 3 equal the same number.
Hex = string_copy(MData,Position+25,1);
script_execute(scr_Za);
XXX = DigA;
Hex = string_copy(MData,Position+26,1);
script_execute(scr_DigA);
Hex = string_copy(MData,Position+27,1);
script_execute(scr_DigB);
YYY = DigA+DigB+1;

Face2C = XXX+YYY;
Face3B = Face2C;

//And we convert the remaining third of face 3.
Hex = string_copy(MData,Position+33,1);
script_execute(scr_Za);
XXX = DigA;
Hex = string_copy(MData,Position+34,1);
script_execute(scr_DigA);
Hex = string_copy(MData,Position+35,1);
script_execute(scr_DigB);
YYY = DigA+DigB+1;

Face3C = XXX+YYY;

/////////////////////////////////////////////////////////
//This following section tediously checks for duplicate//
//data, If it's found then it ignores one of the       //
//duplicates and adds the one that follows             //
/////////////////////////////////////////////////////////

//We start with face 3.

    if Face3A == Face3B then {
    Hex = string_copy(MData,Position+41,1);
    script_execute(scr_Za);
    XXX = DigA;
    Hex = string_copy(MData,Position+42,1);
    script_execute(scr_DigA);
    Hex = string_copy(MData,Position+43,1);
    script_execute(scr_DigB);
    YYY = DigA+DigB+1;
    
    Face3D = XXX+YYY;
    Face3B = Face3D;
    }

    if Face3A == Face3C then {
    Hex = string_copy(MData,Position+41,1);
    script_execute(scr_Za);
    XXX = DigA;
    Hex = string_copy(MData,Position+42,1);
    script_execute(scr_DigA);
    Hex = string_copy(MData,Position+43,1);
    script_execute(scr_DigB);
    YYY = DigA+DigB+1;
    
    Face3D = XXX+YYY;
    Face3C = Face3D;
    }

    if Face3B == Face3C then {
    Hex = string_copy(MData,Position+41,1);
    script_execute(scr_Za);
    XXX = DigA;
    Hex = string_copy(MData,Position+42,1);
    script_execute(scr_DigA);
    Hex = string_copy(MData,Position+43,1);
    script_execute(scr_DigB);
    YYY = DigA+DigB+1;
    
    Face3D = XXX+YYY;
    Face3C = Face3D;
    }

////////////////////////////////////////////

    if Face2A == Face2B then {
    Hex = string_copy(MData,Position+33,1);
    script_execute(scr_Za);
    XXX = DigA;
    Hex = string_copy(MData,Position+34,1);
    script_execute(scr_DigA);
    Hex = string_copy(MData,Position+35,1);
    script_execute(scr_DigB);
    YYY = DigA+DigB+1;
    Face2D = XXX+YYY;
    Face2B = Face2D;
    }

    if Face2A == Face2C then {
    Hex = string_copy(MData,Position+33,1);
    script_execute(scr_Za);
    XXX = DigA;
    Hex = string_copy(MData,Position+34,1);
    script_execute(scr_DigA);
    Hex = string_copy(MData,Position+35,1);
    script_execute(scr_DigB);
    YYY = DigA+DigB+1;
    Face2D = XXX+YYY;
    Face2C = Face2D;
    }

    if Face2B == Face2C then {
    Hex = string_copy(MData,Position+33,1);
    script_execute(scr_Za);
    XXX = DigA;
    Hex = string_copy(MData,Position+34,1);
    script_execute(scr_DigA);
    Hex = string_copy(MData,Position+35,1);
    script_execute(scr_DigB);
    YYY = DigA+DigB+1;
    Face2D = XXX+YYY;
    Face2C = Face2D;
    }
    
/////////////////////////////////////////////

    if Face1A == Face1B then {
    Hex = string_copy(MData,Position+25,1);
    script_execute(scr_Za);
    XXX = DigA;
    Hex = string_copy(MData,Position+26,1);
    script_execute(scr_DigA);
    Hex = string_copy(MData,Position+27,1);
    script_execute(scr_DigB);
    YYY = DigA+DigB+1;
    
    Face1D = XXX+YYY;
    Face1B = Face1D;
    }

    if Face1A == Face1C then {
    Hex = string_copy(MData,Position+25,1);
    script_execute(scr_Za);
    XXX = DigA;
    Hex = string_copy(MData,Position+26,1);
    script_execute(scr_DigA);
    Hex = string_copy(MData,Position+27,1);
    script_execute(scr_DigB);
    YYY = DigA+DigB+1;
    
    Face1D = XXX+YYY;
    Face1C = Face1D;
    }

    if Face1B == Face1C then {
    Hex = string_copy(MData,Position+25,1);
    script_execute(scr_Za);
    XXX = DigA;
    Hex = string_copy(MData,Position+26,1);
    script_execute(scr_DigA);
    Hex = string_copy(MData,Position+27,1);
    script_execute(scr_DigB);
    YYY = DigA+DigB+1;
    
    Face1D = XXX+YYY;
    Face1C = Face1D;
    }
//////////////////////////////////////////////////

//Writes the full line to be written to the file to 'STRINGWRITE' variable
STRINGWRITE += string(Face1A) + ' ';
STRINGWRITE += string(Face1B) + ' ';
STRINGWRITE += string(Face1C);

//This is more personal. Basically, it checks for duplicate values, or those that exceed the
//vertice number.
if Face1A == Face1B or Face1B == Face1C or Face1A == Face1C then {STRINGWRITE += string(Face1C) + 'ERROR';}
if Face1A > 2508 or Face1B > 2508 or Face1C > 2508 then {STRINGWRITE += 'FALSEFALSE';}

//Write 'STRINGWRITE' variable to file 'MWrite', then make a line break.
file_text_write_string(MWrite,STRINGWRITE);
file_text_writeln(MWrite);

//This mainly checks if there was room for face 2 before '98 00'... I know I should have checked this earlier
//but I didn't. If your still confused, it's like if in the hex, the last thing before '98 00' was
//the third part of Face 1, and no more room for faces 2 and 3 to finish.
TESTSTRING = string_copy(MData,Position,27);
if string_pos('9800',TESTSTRING) != 0 && string_pos('009800',TESTSTRING) == 0 then {
//Once again
STRINGWRITE = 'f '
STRINGWRITE += string(Face2A) + ' ';
STRINGWRITE += string(Face2B) + ' ';
STRINGWRITE += string(Face2C);
//And another personal check
if Face2A == Face2B or Face2B == Face2C or Face2A == Face2C then {STRINGWRITE += string(Face2C) + 'ERROR';}
if Face2A > 2508 or Face2B > 2508 or Face2C > 2508 then {STRINGWRITE += 'FALSEFALSE';}
//Write and break.
file_text_write_string(MWrite,STRINGWRITE);
file_text_writeln(MWrite);
}

TESTSTRING = string_copy(MData,Position,35);
if string_pos('9800',TESTSTRING) != 0 && string_pos('009800',TESTSTRING) == 0 then {
//And again
STRINGWRITE = 'f '
STRINGWRITE += string(Face3A) + ' ';
STRINGWRITE += string(Face3B) + ' ';
STRINGWRITE += string(Face3C);
//And again
if Face3A == Face3B or Face3B == Face3C or Face3A == Face3C then {STRINGWRITE += ' ' + string(Face3C) + 'ERROR';}
if Face3A > 2508 or Face3B > 2508 or Face3C > 2508 then {STRINGWRITE += 'FALSEFALSE';}
//Write and break
file_text_write_string(MWrite,STRINGWRITE);
file_text_writeln(MWrite);
}

Position += 24;

I didn't add the declare variables, because there's really nothing special about them. This code just repeats until it reaches the end of the file.

Edit: Hm.. well I'm sure the gist of the code will be helpful to you. Problem is, it came up with errors when I tried to run it (ok not errors, but more hex was skipped than usual). It was mainly because in this version, I shortened it down significantly. I'll get it fixed when I can.
 
Last edited:
OP
Tcll

Tcll

Complexity == Fun >:3
hmm... the code looks a little like C++

but this looks pretty easy to interpret...

and you used the same indexing mode that I did... XD
here's my "before edit" code if you want to get an idea... :)
Code:
import struct as S
dat = open("import.dat", 'rb')#import dat
tmp = open("hex faces.txt", 'w')#temporary txt file
# for DNA face strip
obj = open("export.obj", 'w')
#mtl = open("export.mtl", 'w')#WIP
 
def HexToDec(h):#perfected
    return float(S.unpack("<h", S.pack("<H", int((h.encode('hex')), 16)))[0])
 
def vert(v): 
    return (HexToDec(v)* 0.01).__str__()
    #v x y z
 
def face (f):
    if (f == '0000'):
        return ''
    else:
        return int(HexToDec(f)+1).__str__()+"/1/"
 
def normal (n):#face normals (WIP)
    if (f == '0000'):
        return ''
    else:
        return +int(HexToDec(n)/32767)#.__str__()
 
t0 = dat.read(32)#header
a = 0
while (a == 0):
    v = "v "+vert(dat.read(2))+" "+vert(dat.read(2))+" "+vert(dat.read(2))
    if (v == 'v 0.0 0.0 0.0'):
        a = 1
 
        while (a == 1):
            h = dat.read(1).encode('hex')+dat.read(1).encode('hex')
            if (h == '9'+h[1]+'00'):#primitive type
                a = 2
 
                i = dat.read(1).encode('hex')#index count
                index = h[2]+h[3]+i #0008 index offset
 
                while (a == 2):
                    ft1 = dat.read(4).encode('hex')
                    ft2 = dat.read(4).encode('hex')
                    ft3 = dat.read(4).encode('hex')
                    #moved forward by 12
                    s = dat.seek(-8,1) #move back by 8
 
                    if (ft3 == '00'):#end of file
                        tmp.close
 
                    f1 = ft1[0]+ft1[1]+ft1[2]+ft1[3]
                    f2 = ft2[0]+ft2[1]+ft2[2]+ft2[3]
                    f3 = ft3[0]+ft3[1]+ft3[2]+ft3[3]
 
                    if (f1 != f2 and f2 != f3 and f3 != f1):
                        #if faces are valad (thanx revel8n)
                        tmp.write(f1+"\n"+f2+"\n"+f3+"\n") #DNA face strip
 
                    # you can ignor this code right now, as it didn't work
                    """
                    f1 = (f1)
                    f2 = (f2)
                    f3 = (f3)
                    n1 = ft1[4]+ft1[5]+ft1[6]+ft1[7]
                    n2 = ft2[4]+ft2[5]+ft2[6]+ft2[7]
                    n3 = ft3[4]+ft3[5]+ft3[6]+ft3[7]
                    n1 = (n1)
                    n2 = (n2)
                    n3 = (n3)
                    if ((f1 != f2) and (f2 != f3) and (f3 != f1)):
 
                        f = "f "+face(f1)+normal(n1).__str__()+" "+face(f2)+normal(n2).__str__()+" "+face(f3)+normal(n3).__str__()
                        s = dat.seek(-8,1)
                        #if (f == "f /1/1 /1/1 /1/1"):
                        if (f3 == ''):#(f == "f 13414/1/1 13927/1/1 14133/1/1"):
                            a = 3
                            dat.close()
                            obj.close()
                        else:
                            print f
                            obj.write(f+"\n")
                    else:
                        pass
                    """
 
    else:
        #print v
        obj.write(v+"\n")

as you can see, it's not quite working yet, but I'm trying to make it read my DNA strip method...
this is just for ideas anyways, so enjoy... =]
 
Last edited:
OP
Tcll

Tcll

Complexity == Fun >:3
I'm sorry...

I guess I should have been a little more clear on how the DNA strip sequence works...
it starts out with a selection of 3 face offsets
Code:
|06 46|
|06 47|
|06 48|
 06 3A
 06 48 
 06 3B
 06 48
 06 3C
then checks to make sure the offsets are valad (no duplicate data)
if the offset is valad, the face is logged to a temporary file "faces.txt"
if the offset is invalad, the face is skipped...
then the offset is moved down by 1 (or 4)
Code:
 06 46
|06 47|
|06 48|
|06 3A|
 06 48 
 06 3B
 06 48
 06 3C
then that face is checked...
 
OP
Tcll

Tcll

Complexity == Fun >:3
I have made a discovery for you Milun...
and it's also something that revel8n mentioned way earlier.
...see how slow I am... :(

90 00 09 ;this contans the number of listed faces
04 DF 04 FA 02 7C
04 DE 04 F9 02 7C
05 E3 05 FD 02 7C
04 18 04 33 02 7C
04 17 04 32 02 7C
03 EF 04 0A 02 7C
01 76 01 84 02 7C
02 72 02 7F 02 7C
02 62 02 6F 02 7C
98 00 0A ;(or 10)
02 EC 03 07 02 7C
03 F5 04 10 02 7C
02 EA 03 05 02 7C
03 F6 04 11 02 7C
02 E9 03 04 02 7C
03 F6 04 11 02 7C
04 FA 05 15 02 7C
03 F6 04 11 02 7C
04 FB 05 16 02 7C
03 F5 04 10 02 7C
(this was taken from my import.dat file.)

hovever, the normals would more likely be in the "02 7C" group
I think I'm going to go back to this
it makes more sense this way
at least I can index that by something...

however my DNA converter did seem like a good idea...
I'm not gonna toss that in the trash just yet

I still don't get the differance between the 90 and 98 flags
maybe 98 means smooth and 90 means solid...
IDK yet... I'll have to look into that...
 
Last edited:
OP
Tcll

Tcll

Complexity == Fun >:3
look at this: 8O

98 00 04
03 06 49 05 C2 02 63
03 05 11 04 91 02 5E
15 07 F7 07 C9 02 49
03 05 18 04 98 03 FD

these are player faces...
as tou can see they fall along the same lines as toy faces...

but that extra byte is what gets me...
but that's mainly what causes player models to look like they went through a blender...

btw: my first code worked!
it came out like your first time Milun.

and thanks for that revel8n
I'll look at those links a little later...
working on both computers right now.
EDIT: that first link is already open on my 2nd cpu... XD
 
Last edited:
OP
Tcll

Tcll

Complexity == Fun >:3
that info in the 2nd link along with the info you supplied was very helpful...
I've got a new equation in my head and I can't wait to test it.:bouncy:
 

Top