Omnimaga

Calculator Community => TI Calculators => Axe => Topic started by: GreenFreak on February 09, 2013, 07:34:09 am

Title: What I've done?! O.o
Post by: GreenFreak on February 09, 2013, 07:34:09 am
After writing some programs on my ti 84+, I made it to get something work O.o never mind that i am able to do sth. like that O.o

a little buggy and slowy though running at 15mhz..

can someone help me please to speed this up? :(

i have to fix the fishbowl-effect btw..
Title: Re: What I've done?! O.o
Post by: TIfanx1999 on February 09, 2013, 08:35:48 am
Is this the beginnings of a raycaster?
Title: Re: What I've done?! O.o
Post by: GreenFreak on February 09, 2013, 12:10:58 pm
Yes ;)
Title: Re: What I've done?! O.o
Post by: epic7 on February 09, 2013, 01:33:28 pm
Dangit, I wish I could do that :P
Title: Re: What I've done?! O.o
Post by: DJ Omnimaga on February 09, 2013, 02:06:34 pm
Did you attempt doing raycasting or did you accidentally create it? O.O
Title: Re: What I've done?! O.o
Post by: fb39ca4 on February 09, 2013, 07:45:11 pm
To remove the fisheye effect, you will want to calculate the distance of the walls not from the camera position, but from a line that goes through the camera position and is perpendicular to the view direction.
Title: Re: What I've done?! O.o
Post by: TIfanx1999 on February 09, 2013, 09:21:21 pm
Looks like a nice beginning. :) I'm sure you'll have fun optimizing it.
Title: Re: What I've done?! O.o
Post by: Deep Toaster on February 10, 2013, 10:27:26 pm
All you have to do to remove the fishbowl effect is multiply by cos(θ) where θ is the angle from dead-ahead (see http://www.permadi.com/tutorial/raycast/rayc8.html for an explanation).

Nice job—raycasting is always fun :D
Title: Re: What I've done?! O.o
Post by: Sorunome on February 10, 2013, 10:55:27 pm
What is raycasting?
Title: Re: What I've done?! O.o
Post by: epic7 on February 10, 2013, 11:05:57 pm
I can't really give a good description myself, but the graphics kinda look like dis:
(http://qt-project.org/doc/qt-4.8/images/raycasting-demo.png)

http://en.wikipedia.org/wiki/Ray_casting
Title: Re: What I've done?! O.o
Post by: Sorunome on February 10, 2013, 11:07:32 pm
Sounds interesting, good luck with it! :D
Title: Re: What I've done?! O.o
Post by: fb39ca4 on February 10, 2013, 11:56:38 pm
What is raycasting?
It means projecting a ray into an environment to render it. In this case, rays are cast into a 2D grid of tiles, one for ever column of the screen, and the distance the rays travel is used to calculate the vertical height of the wall rendered.
Title: Re: What I've done?! O.o
Post by: GreenFreak on February 11, 2013, 04:59:17 am
All you have to do to remove the fishbowl effect is multiply by cos(θ) where θ is the angle from dead-ahead (see http://www.permadi.com/tutorial/raycast/rayc8.html for an explanation).

HAHAHA ;D I used this website to create this ;D
I don't understand removing the fishbowl-effect though.. in other words: If I multiply cos(r1) (the angle of the ray being cast) with the calculated distance, the result looks somehow... wierd..

Did you attempt doing raycasting or did you accidentally create it? O.O

It was my goal to create a raycastern ;)

__________

Can someone help me to optimize this? I dont know how to do that :/
Title: Re: What I've done?! O.o
Post by: MGOS on February 11, 2013, 08:20:06 am
Some time ago, I made my own raycaster, however I halted the project... :/ I need to finish it some day

Yours looks awesome so far :)
Looking at your code, I realized that it is quite slow. You only draw 1/4 segments of the screen, and it is running at 15 Mhz. I'm not an expert at raycasting, but I think you need to restructure parts of the code to really optimize it. Still, here are some minor optimization tricks you could use (but I don't think they really matter that much):

Code: [Select]
Pt-Off(0,,Pic0,L3)
If pxl-Test(V/8,W/8,L3)
Using a sprite is a cool idea to store the map, but the pixel-test function is incredible slow (and you're doing that a lot each frame!). Try directly accessing the data, e.g. in an 2d array/matrix etc.



The next optimization helps almost everywhere:
If size doesn't matter, use a bunch of /2 instead of dividing by a power of 2. For example:
A/2/2/2 is faster than /8
This trick works due to the fact that /2 is replaced by a shift operation, whereas every other division calls a routine to divide (which is kinda slow)

Code: [Select]
√(((abs(X-V)²)+(abs(Y-W)²)))→GHere you can leave out the abs(), because squaring gets rid of the sign. You don't even need the first parenthesis. So:
Code: [Select]
√(X-V²+(Y-W)²)→G


Code: [Select]
If r1<64 or (r1>192)Almost in every case you can substitute a logic "or" by an addition.
Code: [Select]
If r1<64 + (r1>192)


I think the slowest part of your code is this, I don't know how to optimize this though, because I don't understand what you want to do with that.
Code: [Select]
Lbl TH
abs(Y-W)*128//sin(r1-r2)*cos(r1-r2)//128→U
r1<128?U+X→V,X-U→V
Return

Lbl TV
abs(V-X)*128//cos(r1)*sin(r1)//128→U
Return
This code looks slow because of signed division and trigonometry. These functions are also called a lot each frame!



Also, if you need a function only once in the code, you can type it inline where you need it to save some bytes and cycles without the call.
If you want to keep readability, you can include them in another program.
Also, what helps reading the code is the C++ style function calling syntax:
Function(arguments) instead of sub(Function,arguments)
For example:
Code: [Select]
sub(TH,r1,128) becomes TH(r1,128)


I guess that's my part for now, maybe I take a closer look on it later. I hope it helps you a bit and good luck with your project.

Title: Re: What I've done?! O.o
Post by: Matrefeytontias on February 11, 2013, 10:15:20 am
Something you absolutely need to know : if you want to use trig, just build some LUTs (look-up tables, tables to hold constant values instead of recalculating them) and leave sin() and cos() alone. Do that at the really beginning of your code :

:E90D3→°SinLUT+2→°CosLUT
:L1→SinLUT+256→CosLUT       // L1 or whatever free RAM area of at least 512 bytes
:~1       // the negate sign, not the minus
:For(256)    // 256 possible angles, from 0 to 255
:sin(+1→r1)→{r1+SinLUT}
:cos(r1)→{r1+CosLUT}
:r1
:End


And then, replace all of your sin(r1) with sign{r1+SinLUT} and all of your cos(r1) with sign{r1+CosLUT}, but you'll have to make sure that r1 can't go above 255. You'll have a great speed gain, you'll see.
Title: Re: What I've done?! O.o
Post by: GreenFreak on February 15, 2013, 02:45:38 am
Big thanks to MGOS! You helped me a lot ;)

Something you absolutely need to know : if you want to use trig, just build some LUTs (look-up tables, tables to hold constant values instead of recalculating them) and leave sin() and cos() alone. Do that at the really beginning of your code :

:E90D3→°SinLUT+2→°CosLUT
:L1→SinLUT+256→CosLUT       // L1 or whatever free RAM area of at least 512 bytes
:~1       // the negate sign, not the minus
:For(256)    // 256 possible angles, from 0 to 255
:sin(+1→r1)→{r1+SinLUT}
:cos(r1)→{r1+CosLUT}
:r1
:End


sry, but I don't understand this :( It seems to be highly optimized.. Can you give me a less optimized version, so that I can understand it? I mean, I want to understand "my" code :/

Thanks though, a LUT is a good idea ;)
Title: Re: What I've done?! O.o
Post by: Matrefeytontias on February 15, 2013, 04:48:13 am
Basically, you calculate the sinus and cosinus of all of the 256 possible angles, and then store them in order to retrieve them rather than calculating them many times. Here's a non-optimized equivalent :

:E90D3->°SinLUT+2->°CosLUT          // gives two names to two numbers
:L1->SinLUT+256->CosLUT
:For(A,0,255)
:sin(A)->{A+SinLUT
:cos(A)->{A+CosLUT
:End

Title: Re: What I've done?! O.o
Post by: Augs on February 15, 2013, 01:15:23 pm
I made a raycaster, the way I got rid of the fishbowl affect was to make the "side-rays" "jump" more. Therefore their reading will be less. If you understand what I mean. It's like making the walls on the side of your screen show up bigger.
Title: Re: What I've done?! O.o
Post by: GreenFreak on February 15, 2013, 01:30:06 pm
:E90D3->°SinLUT+2->°CosLUT          // gives two names to two numbers
:L1->SinLUT+256->CosLUT

I still don't understand these two lines..  :-\
saving L1 into something makes no sense to me :(

Can you pls explain this a little more easy?
Title: Re: What I've done?! O.o
Post by: MGOS on February 15, 2013, 02:25:14 pm
Address->°Name will create a custom variable called “Name" at the given address. You can call the varables how you want, in this case CosLUT or SinLUT. The address should be some empty ram area at least 2 bytes large, since the varables in axe are all 16 bit - at that address the value of the variable is stored. Once you created a new variable, you can use them just like any other variable A-Z or theta.
In the second step you make those variables point to some free ram (L1 and L1+256), so now they hold the the address of the both areas which are use as LUTs.
Title: Re: What I've done?! O.o
Post by: Hayleia on February 15, 2013, 02:29:19 pm
:E90D3→°SinLUT+2→°CosLUT
:L1→SinLUT+256→CosLUT       // L1 or whatever free RAM area of at least 512 bytes
:~1       // the negate sign, not the minus
:For(256)    // 256 possible angles, from 0 to 255
:sin(+1→r1)→{r1+SinLUT}
:cos(r1)→{r1+CosLUT}
:r1
:End

Why not use constant pointers instead of variables, like this ?
:L1→°SinLUT+256→°CosLUT       // L1 or whatever free RAM area of at least 512 bytes
:~1       // the negate sign, not the minus
:For(256)    // 256 possible angles, from 0 to 255
:sin(+1→r1)→{r1+°SinLUT}
:cos(r1)→{r1+°CosLUT}
:r1
:End
Title: Re: What I've done?! O.o
Post by: Matrefeytontias on February 15, 2013, 03:53:17 pm
With this way of thinking, you can still directly use L1.
Title: Re: What I've done?! O.o
Post by: Hayleia on February 16, 2013, 01:07:58 am
With this way of thinking, you can still directly use L1.
True, but renaming it makes the code more readable, and there is still the comment "or whatever free RAM area of at least 512 bytes" ;)