Tuesday, December 23, 2014

Recursion Surgeon

                     Hilo,Halo,Howdayado! On this post I'm going to teach you about recursion. What is recursion you might ask? Well I'll tell you. You know how in our last program we used a loop? Well we're going to replace that loop with recursion,which is when a procedure calls itself instead of doing some sort of jump,which takes us back to the beginning of the procedure,so since we don't choose where we jump back to,we're going to have to make a few changes to our program.

Speaking of which, here's the program:


.586
.model flat, c
.stack 100h
.data

; gcd(10, 4), gcd(28, 21), gcd(12, 8),
left dword 11, 28, 12
right dword 4, 21, 8

.code

doit proc
  push eax
  push ebx
  push ecx
  xor eax,eax
  xor ecx,ecx
  doagain:
    sub esp,4
    push left[ecx]
push right[ecx]
call gcd
pop ebx
add eax,ebx
add ecx,4
cmp ecx,12
  jl doagain
  pop ecx
  pop ebx
  pop eax
 ret

doit endp

gcd proc
push eax
push ebx
push edx
mov eax,[esp + 20]       ; eax is left
mov ebx,[esp + 16]       ; ebx is right
cmp ebx, 0 ; We are done when right is zero
je weAreDone
xor edx,edx
div ebx
mov eax,ebx
mov ebx,edx
sub esp,4
push eax
push ebx
call gcd
pop eax
weAreDone:
; eax has the greatest common divisor
mov [esp + 24],eax
pop edx
pop ebx
pop eax

    ret 8

gcd endp

end

                We don't change anything in doit so let's just talk about gcd and what we change in there. Once we get to gcd our stack will look like this:





                    I'll explain the stack from top to bottom: At the bottom of the stack we have the return address that takes us back to main because that's the very first thing we do when we go into our program,next we have the 3 saved registers for our no trace coding,but just because I called them rand doesn't mean they're just a bunch of random numbers,they are those numbers for a reason,I just called them rand because they're always going to be a different number so I can't confirm them with a fixed value. Next we have our little slot for our return value,and our inputs left and right,and at the top we have the return address back from gcd to doit.

The first time through gcd we have our saves which still aren't a fixed value for our procedure,our return value slot,our inputs,and our return address:



The second time we have our saves which are procedure values this time around,our slot,inputs,and address:






The third time we have our saves,slot,inputs,and address:




The fourth time we only have our saves because we're at the base case which is when right is 0 and since we do the compare right after the saves we jump down to where we unwind the stack:


      The first thing we change in gcd is we get rid of our jump address,because we don't need it anymore,and the next thing we change is before gcd calls itself we do the same thing that we do in doit just before we call gcd,we subtract 4 from the esp to make a slot for our return value,and push the inputs onto the stack so that we can access them through the esp. Another thing I'd like to point out is that since we call gcd from inside itself when we hit the return we return to the instruction right after the call so then we hit the return again and again,meanwhile we're popping a ton of values off the stack. You might be thinking: "Wait a minute,if we do that aren't we going to get a ton of random values?" well the answer is no because since we do the same thing that we do in doit before the call and since gcd calls itself and we go back to the beginning we do all those pushes,while doing these instructions we are doing something called unwinding the stack and eventually we get to the return that takes us back to doit and then we switch to the next set of numbers and call gcd. Well ya that's all cool,but the true beauty of recursion is that (especially with gcd) when you go back to the beginning if you've set up the code right the inputs are ready,the stack's ready,everything's ready to go around again,take the gcd of 11,and 4 for instance,which is the one I'm showing you in the pictures.

1st time gcd(11,4) = gcd(4,11 % 4) = gcd(4,3)
2nd time gcd(4,3) = gcd(3,4 % 3) = gcd(3,1)
3rd time gcd(3,1) = gcd(1,3 % 1) = gcd(1,0)
4th time gcd(1,0) = 1

                            The first time around 11,and 4 are on the stack,so we take them and mod them together which turns the 11 into a 3,then we push our numbers onto the stack again and go to the second time and keep changing the inputs on the stack etc.etc.etc.,and that's the beauty of it: we have our inputs,mod them together,switch them go again. 



WELL TTFN, TA TA FOR NOW!!!!!!!!!!!!!!!!!!!

Thursday, December 4, 2014

Adding upper towards upwards

                            On this post I changed the program so that it brings the gcd of every set of numbers and adds them together,and also performs no-trace-coding which means we save the registers and restore them so it's like the procedure that changed them was never called.





Here's my program:

.586
.model flat, c
.stack 100h
.data

; gcd(10, 4), gcd(28, 21), gcd(12, 8),
left dword 10, 28, 12
right dword 4, 21, 8

.code

doit proc
  push eax
  push ebx
  push ecx
  xor eax,eax
  xor ecx,ecx
  doagain:
    sub esp,4
    push left[ecx]
push right[ecx]
call gcd
add esp,8
pop ebx
add eax,ebx
add ecx,4
cmp ecx,12
  jl doagain
  pop ecx
  pop ebx
  pop eax
 ret

doit endp

gcd proc
push eax
push ebx
push edx
mov eax,[esp + 20]       ; eax is left
mov ebx,[esp + 16]       ; ebx is right
again:
xor edx,edx                   ; zeroing out edx to prevent Integer overflow
div ebx                          ; divides left by right
cmp edx, 0       ; We are done when remainder is zero
je weAreDone

mov eax,ebx       ; we have a new left
mov ebx,edx                 ; our remainder is our new right
jmp again                      ; repeat

weAreDone:
; ebx has the greatest common divisor
mov [esp + 24],ebx
pop edx
pop ebx
pop eax

    ret

gcd endp

end


                               You might notice something that wasn't there before,a subtraction by four from the esp. I put that in because when we subtract 4 from the esp it goes up four bytes which is one space up which opens up a little spot,and before that we push eax,ebx,and ecx to the top of the stack. When we do that we are saving the values that those registers have when we first get to doit so that we can restore them later for main. Then we take eax and xor it because we want to use it to add up the gcd's and ecx is our indexer. Then we push left and right to the top of the stack and call gcd placing the return address at the top of the stack. Once we get to gcd we save the registers that we change in gcd for doit and then place left and right in eax and ebx. Once we get to weAreDone after the other parts of the procedure we place the gcd (which is currently in ebx) into that empty slot we created with the subtraction and pop the rest of the registers values in doit back into them,and that's very important because for example: even though eax is used in gcd it's also used in doit as our sum so we have to restore it to the amount that it was in doit or else we're stomping on our sum,and then return to doit leaving right at the top of the stack. Once we get back to doit at the instruction after the call we add 8 to the esp which leaves the return value (our gcd) at the top of the stack. Then we pop it into ebx and add that to eax which in doit is the sum of all of the gcd's. Then when ecx (our indexer) reaches 12 we go down to the pops and restore eax,ebx,and ecx to their original values before we even called doit.     



WELL TTFN,TA TA FOR NOW!!!!!!!!!!!!!!!!!!!!
















Saturday, November 29, 2014

Cleanup time....dun dun DUN!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

                                      On this post I'm going to show you how I cleaned up my previous program and explain why.


Here's my modified program:




.586
.model flat, c
.stack 100h
.data

; gcd(10, 4), gcd(31415, 14142), gcd(3241343, 948324),
; gcd(31243,68455), gcd(75324,729345), gcd(327256,647384)
left dword 10, 31415, 3241343, 31243, 75324, 327256
right dword 4, 14142, 948324, 68455, 729345, 647384


.code

doit proc
  xor ecx,ecx
doagain:
    push left[ecx]
push right[ecx]
call gcd
add esp,8
add ecx,4

cmp ecx,24
jle doagain
 ret

doit endp

gcd proc
mov eax,[esp + 8]       ; eax is left
mov ebx,[esp + 4]       ; ebx is right
again:
xor edx,edx                 ; zeroing out edx to prevent Integer overflow
div ebx                        ; divides left by right
cmp edx, 0     ; We are done when remainder is zero
je weAreDone

mov eax,ebx     ; we have a new left
mov ebx,edx               ; our remainder is our new right
jmp again                    ; repeat

weAreDone:
; ebx has the greatest common divisor
    ret

gcd endp

end


                            First I moved my compare from the end of gcd into the middle,and the reason we do that is because if we leave the compare at the end then once we've got our greatest common divisor then every thing else after that would just be extra work which is why I moved the compare to right after the division problem,if the 2nd number is 0 we jump straight to the return,and if it's not we just continue and switch all the numbers. Also I changed it so that we only read off of the inputs and we don't change them at all,because it's like doit sent a letter to gcd and if we change the inputs it's like we drew a picture all over that letter. And now since we use the inputs a lot less we use the registers a lot more,and a good thing about that is using the registers is way faster. Also I changed my commentary.


WELL TTFN,TA TA FOR NOW!!!!!!!!!!!!!!!!!!!!

Monday, November 24, 2014

WAITER,QUADRUPLE THAT ORDER!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

                                        On this post we're going to take the program from the previous post and change it so that it takes 4 sets of numbers and finds the gcd between them one by one.


Her'es the program:



.586
.model flat, c
.stack 100h
.data

;gcd(3241343, 948324), gcd(31243,68455),gcd(75324,729345),gcd(327256,647384)
left dword 3241343, 31243, 75324, 327256
right dword 948324, 68455, 729345, 647384

.code

doit proc
xor ecx,ecx
doagain:
push left[ecx]
push right[ecx]
call gcd
add esp,8
add ecx,4
cmp ecx,16
jle doagain
ret

doit endp

gcd proc
mov eax,[esp + 8]      ; move the larger number of the first division problem into eax
repeatHere:
again:
xor edx,edx             ; zeroing out edx to prevent Integer overflow
mov ebx,[esp + 4]       ; hijacking ecx to represent right in the division problem
div ebx                 ; performing the first division problem of the loop
mov eax,[esp + 4]            
mov [esp + 4],edx       ; preparing the numbers for the next time around
xor edx,edx             ; hijacking edx to represent the 0 in the compare
cmp [esp + 4], edx      ; comparing right to zero because we stop at when the second number becomes zero
jne again               ; if right isn't zero we jump back to the beginning

    ret

gcd endp

end




                                    As you can see it's almost the same as the previous program but with a few small changes,well actually big changes,such as the fact that I now have 2 procedures instead of 1 and that's because a procedure is supposed to do one thing and do it well,also left and right don't appear to be here,but they are. They've been pushed onto the stack which is why we use the stack pointer to represent them. You might think: "Why not just access the stack pointer,and the stack pointer plus 4?" Well we have to skip past the return address of the call to gcd. Also when we get back around to the point where we push left and right onto the stack we take them off the stack by adding 8 to the stack pointer which lowers the stack pointer down to the return address of that call so that we don't have to lower it past all those numbers at the very end kinda like this....



 And the reason it's like that is because gcd isn't supposed to do everything at once,it's supposed to do one thing and do each part of it one at a time,kinda like this dentist cartoon,if you wait to floss for the entire year all the plaque builds up and then it's hard to get it all out,but if you do it consistently every day there will be a lot less plaque so it will be a lot easier.    

WELL TTFN TA TA FOR NOW!!!!!!!!!!!!!!!!!!!!

Wednesday, November 19, 2014

The GREAT,the common,and the divi/sor.......

                                  On this post I'm going to talk about how to get the greatest common divisor between 2 numbers. The greatest common divisor is the largest number they can each be divided by,for example the greatest common divisor between 2,and 3 is 1 because the numbers aren't related,on the other hand the greatest common divisor between 2 and 4 is 2 because the numbers are both even and multiples of 2. I know you're probably thinking " this isn't going to be too hard but too bad for you the numbers we're using are 31415,and 14142,dun dun dun!!!! You might still be thinking that because one is odd and one is even,but what if I told you that you had to show me the step-by-step work to get the greatest common divisor of those 2 numbers? Well that's what we're going to do,but luckily there's a mathematical equation we can use. gcd(31415,14142) = gcd(14142,31415 mod 14142): gcd means "the greatest common divisor of" and mod means you divide 31415 by 14142 and then replace 31415 with the remainder of that division problem so the problem would become (14142,3131) = (3131,14142 mod 3131) and then you'd keep going etc.etc. until your problem would look something like this:





                  Luckily I have a program that can do this,and here it is:



.586
.model flat, c
.stack 100h
.data

left dword 31415
right dword 14142


.code

doit proc
xor ecx,ecx ; zero out ecx to count our loop
again:
mov eax,left    ; move the larger number of the first division problem into eax
mov edx,right   ; moving the larger number of the next division problem into a position where we can move it into left
mov left,edx    ; executing the previous comment
xor edx,edx     ; zeroing out edx to prevent Integer overflow
div right       ; performing the division problem
mov right,edx   ; preparing the numbers for the next time around
inc ecx         ; noting that we have gone around so we can add it to how many times we have already gone around
cmp ecx,10      ; comparing ecx to ten because we stop at 10
jne again       ; if ecx isn't ten we jump back to the beginning

  ret

doit endp

end



                              As you can see I have the code commented and ready to go,so I'll explain how it works: So the first thing I did was grab two pieces of memory,I named one left,and the other right,and the reason I did that is because I needed two places to store the numbers that wouldn't get erased every frame. Then we xor ecx because we need it to be our counter because we need to go around 10 times. Then we move left into eax because eax represents the larger number of the division problem,and then we move right into edx because right contains the larger number of the next problem which needs to be placed in left and you can't move memory into memory,only memory into register or register into memory. Then we move edx into right,and after that we xor edx to prevent Integer overflow. And after that we do the division problem,take the remainder,and move it into right. Afterwards we inc ecx to keep track of how many times we have gone through the loop and eventually we stop at 10,and jne back to again.

                       Well there's an itty bitty problem with this,our chart is in decimal,but when we run the code the numbers are shown in hex,so it's pretty hard to keep track of where you're at in the program
or if the numbers are right,well I've got a solution:



            I made you a hex chart,ta da! This chart will help you keep track of what line you're at and if you have the right numbers.


WELL TTFN,TA TA FOR NOW!!!!!!!!!!!!!!!!!!!!

Friday, November 14, 2014

CopyC++at

                   On this post we're going to take our refactored programs and write them again in C++,so it's like the C++ is copying the assembly.



Here's the program from the COPS and ROBBERS post:




extern "C" void doit();

int myNumbers[] = { 7, 3, 8, 2, 2, 9, 8, 5, 7, 4, 8, 3, 8, 13, 8, 7, 4, 8 };

void main()
{
// doit();
int counter =0;
for (int i = 0; i < 18; i++)
{
if (myNumbers[i] == 8)
{
counter++;
}
}


}


               So first things first,we changed myNumbers into an int because this is C++,and eax is replaced by i,ecx is replaced by counter,instead of 68 we're going until 18 because to get to a different number you only need to add one because myNumbers isn't a dword it's an int,and also we say ++ in C++ which means increment. The for stands for the beginning of the loop,and the only thing we actually have to type is the cmp and CountingCounter because the curly braces take care of everything else so whoopee!!!!!!!!!!


Here's the program from the "I'm looking for someone really small............." post in C++:                                                    

extern "C" void doit();

int myNumbers[] = { 7, 3, 8, 2, 7, 9, 8, 5, 7, 4, 8, 3, 8, 1, 8, 7, 4, 8 };

void main()
{
// doit();
int i =0;
int first = myNumbers[i];
for ( i = 1; i < 18; i++)
{
if (first>myNumbers[i])
{
first = myNumbers[i];
}
}

}

                 On this program I replaced ebx with first,and set that to the first number of myNumbers so that the first number doesn't get used twice in the loop,and for that same reason i starts out in the loop as 1. In the loop we're saying the same thing as the assembly loop,simply "If the amount in first is greater than the amount represented by myNumbers[i] than move that amount into first and eventually that will give us the smallest number in myNumbers.

WELL TTFN TA TA FOR NOW!!!!!!!!!!!!!!!!!!!!




Tuesday, November 11, 2014

To refactor,or not to refactor,that is the question...........

                                     On this post  I'm going to show you how I refactored both the program from the previous post and the post before that one too. Refactoring is cleaning up and simplifying a program so that it's less headache to keep track of.


Here's the program from the previous post refactored:


extern "C" void doit();

void main()
{
doit();
}


.586
.model flat, c
.stack 100h
.data

 myNumbers dword 7,3,8,2,2,9,8,5,7,4,8,3,8,1,8,7,4,8

.code


doit proc
xor eax,eax
mov ebx,myNumbers[eax]

again:
add eax,4
cmp myNumbers[eax],ebx
jge repeatIfNeccesary
mov ebx,myNumbers[eax]
repeatIfNeccesary:
cmp eax,68
jle again
ret

doit endp


end


          The first thing I changed was that I got rid of ecx's involvement in the program,which seems kinda weird,but the reason I did it was because I realized I didn't need a register to represent myNumbers because myNumbers can represent itself. The second thing I changed was instead of jumping to switcheroo I put it in the loop and said jump greater than or equal to repeatIfNeccesary so instead of jumping to the part where we store the smallest number we jump past it if we currently don't need to do it.


Here's the program from the post before that one refactored:



extern "C" void doit();

void main()
{
doit();
}



.586
.model flat, c
.stack 100h
.data

 myNumbers dword 7,3,8,2,2,9,8,5,7,4,8,3,8,13,8,7,4,8

.code


doit proc
 xor eax,eax
 xor ecx,ecx
 again:
 cmp myNumbers[eax],8
 jne repeatIfNeccesary
 add ecx,1
 repeatIfNeccesary:
 add eax,4
 cmp eax,68
 jle again
 ret




doit endp


end

                                 On this program I changed from jumping to CountingCounter to jumping past the instructions inside it if we currently don't need to use them just like in the other program.



   WELL TTFN TA TA FOR NOW!!!!!!!

I'm looking for someone really small...................................

                              We're going to talk about how to find the smallest guy in a crowd. I tweaked my program from the last post,so now instead of finding out how many of the numbers are 8's,we're going to find out which one of the numbers is the smallest.


Here's the program:



The C++ part:


extern "C" void doit();

void main()
{
doit();
}

And the assembly part:


.586
.model flat, c
.stack 100h
.data

 myNumbers dword 7,3,8,2,2,9,8,5,7,4,8,3,8,1,8,7,4,8

.code


doit proc
xor eax,eax
xor ecx,ecx
mov ebx,myNumbers[eax]
again:
add eax,4
mov ecx,myNumbers[eax]
cmp ecx,ebx
jl switcheroo
back:
cmp eax,68
jle again
ret
switcheroo:
mov ebx,ecx
jmp back


doit endp


end

             So get all that typed in and I'll explain how it works.

             This is how it works,just like the program from the last post we xor eax by eax,and ecx by ecx,and also we move myNumbers into ebx,except we only do that once because of the again. Then as always we add 4 to eax so that we can access the next number of myNumbers,except not because we want to place the next number of myNumbers in ebx,we want to place it in ecx,and here's why.
We take the next number of myNumbers and compare it  to the number currently in ebx and if it is smaller than the number currently in ebx then we jump to switcheroo. In switcheroo we move the number currently in ecx into ebx so that we always  have the smallest number we've seen so far in ebx. Then we jump to back compare eax to 68 and if it is less than or equal to 68 we jump back to again.

                                     WELL TTFN TA TA FOR NOW!!!! 



Monday, November 10, 2014

COPS and ROBBERS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

                      We're going to make a program that finds all of the 8's in a jumble of numbers and then tells you how many of them there are, sorta like cops investigating a bunch of people and trying to find out how many of them are criminals.

Here's the program:




1st the C++ part:


extern "C" void doit();

void main()
{
doit();
}


And then the assembly part:

.586
.model flat, c
.stack 100h
.data

 myNumbers dword 7,3,8,2,2,9,8,5,7,4,8,3,8,13,8,7,4,8

.code


doit proc
xor eax,eax
xor ecx,ecx
again:
mov ebx, myNumbers[eax]
cmp ebx,8
je CountingCounter
back:
add eax,4
cmp eax,68
jle again
ret

CountingCounter:
add ecx,1
jmp back


doit endp


end





So get all that typed in and then I'll explain how it works.

The program starts out in C++, and from there calls doit an assembly procedure.Then we create MyNumbers which is our jumble of people. So how do we find out how many are criminals (8's)? Well first we need 2 registers,eax,and ecx to be completely zeroed out because we're going to use one: eax to access MyNumbers correctly,and we'll use ecx to count how many criminals (8's) there are.Now we say mov ebx MyNumbers and you see how I've got eax in the brackets? Well that's because we're using eax to access MyNumbers,and since eax is currently 0 we will access the first number in MyNumbers. Now since the criminals are 8's we compare ebx to 8 and if it is 8 we would do that jump equal to (je) but I'll get back to that later. That "back" is where we jump to from the je so don't worry about it right now,so next we add 4 to eax because every number is a dword and a dword is 4 bytes. Then we compareeax to 68 because that's the number we stop at. Then we do the jle which means if eax is less than or equal to 68 jump back to again. Now I'll talk about what would happen if ebx was an 8. We would do the je  down to CountingCounter. Then we would add 1 to ecx because we're using it to count how many 8's there are, Then we jump to back.





WELL TTFN TA TA FOR NOW!!!!!!!!!!!!!!!!!!







Monday, October 27, 2014

SPACESHIP!!!!!!!!!!!!!!!!!!!!!!!!!!!SPACESHIP!!!!!!!!!!!!!!!!!!!!SPACESHIP!!!!!!!!!!!!!SPACESHIP!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Hi! Long time no see huh! Well I've been working on a little something that I'm going to show you now. I've been working on a program that makes a little spaceship video game! You drive a little spaceship around a black screen and it bounces off the walls. You can adjust the speed (speed = magnitude),and direction (magnitude + direction = velocity) of the spaceship anddddddd, it will never leave the screen!





Here's my program:



#include <Core.h>
#include <Vector.h>

Vector position;
Vector velocity;

void checkin ( )
{
if(Core::Input::IsPressed(Core::Input::KEY_LEFT))
{
velocity.x = velocity.x - 1;
}
if(Core::Input::IsPressed(Core::Input::KEY_RIGHT))
{
velocity.x = velocity.x + 1;
}
if(Core::Input::IsPressed(Core::Input::KEY_UP))
{
velocity.y = velocity.y - 1;
}

if(Core::Input::IsPressed(Core::Input::KEY_DOWN))
{
velocity.y = velocity.y + 1;
}
}






bool MyUpdateFn( float dt )
{
checkin ();

position = position +  velocity * dt;



if (position.x > 800)
{
velocity.x = velocity.x * -1;
}

if (position.x < 0)
{
velocity.x = velocity.x * -1;
}

if (position.y > 800)
{
velocity.y = velocity.y * -1;
}


if (position.y < 0)
{
velocity.y = velocity.y * -1;
}
return false;
}


void drawship (Core::Graphics& graphics)
{
Vector a(-50,50);
Vector b(-50,-50);
Vector c(50,-50);
Vector d(50,50);
Vector e(0,-100);

Vector aPrime = position + a;
Vector bPrime = position + b;
Vector cPrime = position + c;
Vector dPrime = position + d;
Vector ePrime = position + e;

graphics.DrawLine(aPrime.x,aPrime.y,bPrime.x,bPrime.y);// 1
graphics.DrawLine(aPrime.x,aPrime.y,dPrime.x,dPrime.y);// 4
graphics.DrawLine(bPrime.x,bPrime.y,cPrime.x,cPrime.y);// 2
graphics.DrawLine(cPrime.x,cPrime.y,dPrime.x,dPrime.y);// 3
graphics.DrawLine(ePrime.x,ePrime.y,cPrime.x,cPrime.y);// 5
graphics.DrawLine(ePrime.x,ePrime.y,bPrime.x,bPrime.y);// 6



}


void MyDrawFn( Core::Graphics& graphics)
{
// drawship(graphics);
}


int main()
{
Core::Init("Collin", 800, 800);
Core::RegisterUpdateFn(MyUpdateFn);
Core::RegisterDrawFn(MyDrawFn);
Core::GameLoop();
}



As you can see, it's a ton of code. So I'll start explaining it so we're not here for a century or 2. At the top we make our 2 vectors: position, and velocity. Next we make our void checkin procedure. After that we make our bool MyUpdateFn .  Then we type in the void drawship procedure,and after that we type in void MyDrawFn,and finally.........last but not least...........int........main!! Once you've gotten all that typed in we'll take a peek at how it fits together to make a game.




HI THERE!! REMEMBER ME!!?? OF COURSE YOU DO!! So the reason we make our 2 vectors is because we're gonna need vectors right? The reason we call them position and velocity is because one of them represents the ships' position and the other represents the ships' velocity. The position of the ship is where it's at on the screen and the velocity of the ship is what direction the ship is going in and how fast it's going in that direction,so whenever you change the ships' velocity you indirectly change the ships position so together velocity and position make the ship move. But that  doesn't mean that you have to change velocity to change position, in fact position has to be updated every single frame or else the ship stops when you let go of the arrow keys and then you have to start again at the lowest speed. The top procedure: void checkin controls which direction the ship is going in and how fast it's going in that direction,those little bits of code each control one of the arrow keys, you see how on left we're taking away from velocity.x and on right we are adding to it? Plus when we do up, we subtract from velocity.y,and when we do down  we add to it. Then it's off to see bool MyUpdateFn! In MyUpdateFn we make the ship bounce off the "walls" of the screen,here's how we do it. The screen is 800 by 800 pixels right? Well how we make the ship bounce off the walls is this. We say "if position.x is less than 0 or bigger than 800 multiply it by -1 and the same thing with position.y. The reason we multiply them by -1 is because whenever you multiply a number by -1 if it's a positive number it becomes a negative number,and if it's a negative number it becomes a positive number which flips the direction of the ship so whenever the ship hits a wall it goes in the opposite direction at the same speed. Now we're going to talk about my drawship procedure. This procedure as it's name suggests draws the ship on our screen using vectors a,b,c,d, and e and then sets them to the x,and y positions that we want to put the lines that make up the ship between. Now, you're probably wondering, if we set the ship to one position how is it supposed to move?  How we do that is we take these vectors and add them to position so that they will move, and name those new vectors aPrime,bPrime etc. etc. Then we take those Prime vectors and build the ship with them. And everything else after that is stuff my dad put in that I don't know how to explain.


                                           WELL   TTFN TA TA FOR NOW!!!!



Wednesday, June 25, 2014

The Case of the Missing Sphere

 Hi, it's been awhile. I've been working on ray tracing, and I have something new to teach you. Have you ever looked at a really realistic movie made out of computer graphics, or a really good video game and wondered how they made it ? They might have used ray tracing. Ray tracing is using rays and vectors to make a picture.  I've been working on it and I'm going to teach you what I know so far.  We are going
to put a sphere in the middle of a picture and use rays to color it so we can see it. First off we're going to need to place the sphere, and since we need to place it in the middle first we need to figure out how big our screen is. We're not going to use the entire screen, instead we're going to use a smaller 300*300 pixels screen. That means to place the sphere in the middle of the screen we need to place it's origin at -150 y,  150 x, and -300 z, and make it's radius 150. So we have our sphere. Now we need our rays. We need to hit every single pixel with a ray. So that means we need to put a ray at every single pixel. Doing them individually would take forever, so instead we're going to use a loop.

 This loop is going to create new rays and place them at different points.

for(int row = 0 ; row < NUM_PIXELS_Y ; row++)
for(int col = 0; col < NUM_PIXELS_X ; col++)
{
Ray explorer;
explorer.origin.x = -149.5 + col;
explorer.origin.y = -149.5 + row;
explorer.direction.z =-1;
   

Notice that I didn't close it off with a curly brace. That's because this is only the 1st 1/2 of the loop.  We'll get into the second 1/2 later but for now let's focus on this.

Our ray is called explorer, and what's nice about this loop is that after it does explorer it automatically does all the other rays, so we don't have to do another loop along with it. When we say col we mean columns, and obviously row means rows. The "for" part up there is the 1st part of the loop, they're the actions we do to determine if we go into the 2nd part of the loop. So there's int row = 0; which creates row and then makes it 0, then we compare row to NUM_PIXELS_Y;, row++ means increment row(if you don't know what increment means it means add 1) and the next line is the same except col replaces row and  NUM_PIXELS_X; replaces NUM_PIXELS_Y;. Then we have all this stuff about rays' origin. Origin.x is -149.5 + col, and origin.y is -149.5 + row, so as columns goes across and rows goes up and down we end up with rays at every single pixle of our 300*300 screen. And direction.z is the direction of the rays.


glm::vec3 hipotenoose = sphere.origin - explorer.origin;
 float adjacentLength = glm::dot(explorer.direction,hipotenoose);
 glm::vec3 adjacent = explorer.direction * adjacentLength; glm::vec3 opposite = hipotenoose - adjacent; if(glm::length(opposite) < sphere.radius) { 



qimage.setPixel(col,row,qRgb(0xFF,0,0)); }

Now for the 2nd 1/2 of the loop.

We've got our sphere and our rays, and now we have to figure out what rays hit the sphere and what rays don't and what to do if the ray hits the sphere. Here's the math.
                                                       
I know, it looks ridiculous but this is what we do. See we've got our ray which we can tell just by looking at this picture is going to hit the sphere. But the computer doesn't know that, so we need to do some math to figure it out. We've got our sphere, the spheres' origin,the spheres' radius, and our point of the world ( the + ). So 1st we draw a line from the spheres' origin to the rays' origin ( hypotenuse ), a line coming off of the ray ( adjacent ), a line coming off the point of the world to the rays' origin,and a line coming off the point of the world to the spheres' origin. The reason we're drawing these lines from the point of the world is so we can figure out hypotenuse, and how we do that is we say: ray origin - sphere origin = hypotenuse. So now we've got one side but we need the others to. So on to adjacent !!! To figure out adjacent we need to do hypotenuse, dot, rays' direction. Dot sort of means multiplication but you end up with the magnitudes of the vectors you're using and cos theta. So this is what we got from dotting those 2 together: |hypotenuse| |rays ' direction| cos theta. Now we scale it off of the ray's direction and we've got our adjacent! The next part is easy since we've got our hypotenuse and our adjacent now we need to get our opposite. All we have to do is subtract one from the other and we've got our opposite. Then we compare it to the spheres' radius and if it's longer the ray didn't hit  the sphere but if it's shorter the ray did hit the sphere. And the last line of code colors the pixels and you can fiddle around with the numbers to change the color of the sphere.

Detective, case solved!