Wolfenstein / DOOM for Oric : has this been done?

Want to talks about games you like, would like to see developed on the Oric, it's here.
User avatar
Badger
Pilot Officer
Posts: 81
Joined: Sat Sep 22, 2018 10:04 am
Location: Wigan, England

Re: Wolfenstein / DOOM for Oric : has this been done?

Post by Badger »

Excellent effort,

Like you said, with some recoding of the C part into assembly would allow possibly faster rendering and some sort of gameplay thrown in there.

Without knowing how the mapping part works, even a dungeon master style game looks more than feasable.
flag_uk Amateurs built the Ark, Professionals built the Titanic.

User avatar
jbperin
Flying Officer
Posts: 178
Joined: Wed Nov 06, 2019 11:00 am
Location: Valence, France

rax engine + ray casting + glOric

Post by jbperin »

Hi all,

Playing with raycasting and rax engine within a glOric scene.

Only 2 times overclock to record the following screencap:

Sober Mode :
raycasting.gif
raycasting.gif (143.87 KiB) Viewed 849 times
Color Mode :
raycastcolor.gif
raycastcolor.gif (147.16 KiB) Viewed 849 times
Running out of memory ..

User avatar
jbperin
Flying Officer
Posts: 178
Joined: Wed Nov 06, 2019 11:00 am
Location: Valence, France

High Performance Ray Casting On Oric

Post by jbperin »

Hi all,

I'm very glad to release the C source code of a brand new ray casting system dedicated to Oric computers.

I've been working hard over the past few month on how to do ray casting in the most suitable way for Oric.

I started from the equations and try to find the smartest possible way to implement them on the 8 bits processor of the Oric computer.

I came up with a solution which, IMHO, fits nicely the performance of this incredible machine.

In the attached demo, I use Dbug's rendering routine for ultra fast Hires performance.
OricRayCasting.gif
OricRayCasting.gif (189.01 KiB) Viewed 813 times
The source code of this demo is here :
OricRayCasting.zip
(73.22 KiB) Downloaded 30 times
I'm currently working on an assembly language version of this ray casting system.

Stay tuned.

User avatar
xahmol
Flying Officer
Posts: 129
Joined: Sun Jun 28, 2020 7:32 pm
Location: Utrecht, The Netherlands
Contact:

Re: Wolfenstein / DOOM for Oric : has this been done?

Post by xahmol »

Great work! Looks superb!
What a huge step in looks compared to the post before.
Last edited by xahmol on Sat Nov 14, 2020 7:53 pm, edited 1 time in total.

User avatar
ibisum
Wing Commander
Posts: 1373
Joined: Fri Apr 03, 2009 8:56 am
Location: Vienna, Austria
Contact:

Re: Wolfenstein / DOOM for Oric : has this been done?

Post by ibisum »

Astonishing accomplishment, even more binoculars to consider where this will lead to next!

User avatar
Chema
Game master
Posts: 2733
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

Re: Wolfenstein / DOOM for Oric : has this been done?

Post by Chema »

I must say this is impressive indeed. Great work!

User avatar
iss
Wing Commander
Posts: 1155
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

Re: Wolfenstein / DOOM for Oric : has this been done?

Post by iss »

Congrats! (Glop-Glop! ;))

rax
Officer Cadet
Posts: 55
Joined: Tue Jul 24, 2018 3:16 pm

Re: Wolfenstein / DOOM for Oric : has this been done?

Post by rax »

It's moving very well, congratulations :)

User avatar
kenneth
Flight Lieutenant
Posts: 356
Joined: Fri Nov 26, 2010 9:11 pm
Location: France PdD
Contact:

Re: Wolfenstein / DOOM for Oric : has this been done?

Post by kenneth »

Very fast!

User avatar
coco.oric
Squad Leader
Posts: 612
Joined: Tue Aug 11, 2009 9:50 am
Location: North of France
Contact:

Re: Wolfenstein / DOOM for Oric : has this been done?

Post by coco.oric »

JB, you're incredible.
What you've done is a fantastic performance on our lovely computer. This game rendering machine will give ideas to creators for sure.
Thanks for opening a new world on Oric
coco.oric as DidierV, CEO Member
Historic owner of Oric, Apple II, Atari ST, Amiga

User avatar
jbperin
Flying Officer
Posts: 178
Joined: Wed Nov 06, 2019 11:00 am
Location: Valence, France

Re: Wolfenstein / DOOM for Oric : has this been done?

Post by jbperin »

Thank you all for your warm and kind comments.
It is very encouraging and honouring.

I'll keep you posted of new developments when they deserve to be shown.

I can already announce that I:
- solved the memory problem and fastened the ray tracing by translating into assembly language some big part of my C code (I got back 8 ko !! ).
- integrated rax engine

I recently had a bugfixes period (following the porting in assembly language) and now I'm going to work on:
- 3D animated scene
- Rendering enhancement

So it should worth staying tuned .. I hope ..

User avatar
Chema
Game master
Posts: 2733
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

Re: Wolfenstein / DOOM for Oric : has this been done?

Post by Chema »

I am quite impressed and interested in this project. As I told before I always wanted to experiment with this in the Oric, but never got the time (did not write a single line of code!). So I am going to ask a few questions :)

For what I understand, raycasting is a matter of tracing rays from the player's point of view. Usually you set an angle of view of 60 degrees and divide it into the visible columns. In the Oric the max would be 240, but I if you use full scans it could get down to 40. The thing is tracing the ray in the map in the correct direction and check when it collides with a wall. Then you have distance and wall information (colour, texture, whatever). I guess you can use distance to decide brightness and use a pattern to draw the column (either pixel-wide or scan-wide or something in the middle), but most importantly to decide its height. There is a correction with the cosine of the angle so walls in front of you look flat. All that *could* be done at a decent speed in the 6502, I imagine: angles are fixed, so all needed values can be stored in tables, and there are some data structures which can be used to optimize the process of casting the ray (beyond drawing it on the map until you hit something).

If I understood correctly, you optimized all this process with a different approach. Could you elaborate a bit more on this? I am curious.

I always thought the worst part was the rendering. I think the demo is drawing full scans to achieve this speed, thus the ragged borders of the walls. They may work anyway if the speed is kept as it is in the demo. I wonder how flexible the current method is as to be used in a game. For instance, is it double buffered? Can other sprites be rendered with the map? Some sprites will be partially covered with walls... How does using scans instead of one-pixel columns behave when the player wants to aim an enemy? Are you mirroring up and down halves of the viewing area? Could elevations be used? (moving up/down a bit while walking would look terrific).

I was thinking about using a completely unrolled list of sta to draw a column and jump to the drawing code at a given address to start at a given height and end at a given position (patching the sda with an rts, for instance), but that might work well when using a single scan value for all the column.

What about patterns? You can have simple patterns or textures and "scale" them with distance (drawing 1 row every n rows when you are far), but that means more code. And, unless the pattern is constant horizontally, you'll need to figure out which column of the graphic is needed. That should not be too difficult as your map may contain not only wall/nowall, but different values for pattern slices. However, this process looks a bit complex (in CPU time) and more difficult to optimize.

As you can see, I find this quite exciting, so I am eager to learn :)

User avatar
jbperin
Flying Officer
Posts: 178
Joined: Wed Nov 06, 2019 11:00 am
Location: Valence, France

Re: Wolfenstein / DOOM for Oric : has this been done?

Post by jbperin »

Chema wrote:
Sun Nov 15, 2020 9:46 pm
All that *could* be done at a decent speed in the 6502,
Yes but I was targeting the insane speed rather the decent one. :-)

Chema wrote:
Sun Nov 15, 2020 9:46 pm
I imagine: angles are fixed, so all needed values can be stored in tables, and there are some data structures which can be used to optimize the process of casting the ray (beyond drawing it on the map until you hit something).
Dbug's ray casting system uses this very smart approach of ray casting which consists in actually shooting a ray until it hits a block.
My first work had been to rework his demo. I speeded it up a bit and start to fix a little bit the stairs effect. I showed my code to Dbug and he didn't feel like making it available on defence-force repository.
I was very impressed by his principle of filling column by using a patched entry point adress in an unrolled columnn filling routine.
I was also seduced by his idea of actually casting the ray and I still think it is the most efficient approach for tight labyrinths made of block.

I considered that the render routine couldn't possibly be improved (on the speed point of view) so I decided to rather look for an optim on how to compute the distance.

Just like you've just done, I told to myself that the calculation *could* be done at a decent speed in the 6502. Rather than casting the ray, it should be possible to find the distance by computation rather than deduction.
But the problem with this approach is that we have to compute the distance for all wall, for all slice of screen. So the calculation really has to be fast to compete with the iterative approach which automatically find the first wall that cross the ray.

Chema wrote:
Sun Nov 15, 2020 9:46 pm
If I understood correctly, you optimized all this process with a different approach. Could you elaborate a bit more on this? I am curious.
- Computing the distance rather than deducing it.
- Find the most optimized way to compute the distance with a good-enough accuracy

On this second point, I think the two key points are:
- Doing all calculation on logarithmic scales because it avoids division and additions while preserving comparison with native processor instruction.
- Avoiding fixed math arithmetic as long as a pure 8 bits calculation is possible.



And I can witness that the second point was difficult because the C compiler use fake 8 bits type of data.
And truncated 16 bits arithmetic is not the same as 8 bits arithmetic in some case.
For example, when dealing with angle rollover .. the overflow flag of the processor is very valuable and the C compiler doesn't give an easy way to work with it. I had to write things like:

Code: Select all

if (abs(lAngle[RayIdXPoint2] - lAngle[RayIdXPoint1]) > 127){

which is pure non sense because lAngle are signed char values .. but which does what I was wanting:

Code: Select all

		"ldy _RayIdXPoint1;"
		"lda _lAngle,Y;"
		"sta reg7;"
		"ldy _RayIdXPoint2;"
		"lda _lAngle,Y;"
		"sec;"
		"sbc reg7;"
		"bvc VeryWideAngle_03;"

The other very powerful stuff I found (and finally not used) is that:

sin(alpha).cos(beta) - cos(alpha).sin(beta) = sin (alpha - beta)

I was ignorant of this trigonometric relation and re-discoved it as I was looking for a way to do ray casting on non-aligned walls. It turns out that the quantity sin(alpha).cos(beta) - cos(alpha).sin(beta) is very important in this case and the fact that it can be calculated with sin (alpha - beta) can save lots of cycle. There's a function exploiting this trick in the code I provided .. but it is not used because I decided to keep only aligned walls.

NB: this quantity is also very important in texture mapping. I had encountered it when working on texture .. so .. maybe not lost


Chema wrote:
Sun Nov 15, 2020 9:46 pm
I always thought the worst part was the rendering. I think the demo is drawing full scans to achieve this speed, thus the ragged borders of the walls. They may work anyway if the speed is kept as it is in the demo. I wonder how flexible the current method is as to be used in a game.
I have the same questionning .. that's why I'm exploring a text mode rendering in which I could use glOric's z-buffer and frame buffer which are already armed to deal with sprites partially covered with walls and stuffs like that.
Chema wrote:
Sun Nov 15, 2020 9:46 pm
For instance, is it double buffered? Can other sprites be rendered with the map? Some sprites will be partially covered with walls...
At the output of the ray casting procedure, there are two arrays. Each array gives, for each slice of screen:
- the wall number that is crossed on this slice,
- the distance at which it is crossed,

The array with the distance can be used as a one dimension z-buffer to help selecting part of the sprite that are visible. If the distance of the object represented by the sprite is greater than the one in the zbuffer at a given slice index, then the sprite is not visible on this slice.

Chema wrote:
Sun Nov 15, 2020 9:46 pm
How does using scans instead of one-pixel columns behave when the player wants to aim an enemy? Are you mirroring up and down halves of the viewing area? Could elevations be used? (moving up/down a bit while walking would look terrific).
rendering 3D scene with 1D RayCasting consist in exploiting scene symetry .. so the elevation cannot be used .. but I presume there must be a way to displace things by offsetting addresses either in a kind of post processing step or when the screen buffer is copied to the screen memory.
Chema wrote:
Sun Nov 15, 2020 9:46 pm
I was thinking about using a completely unrolled list of sta to draw a column and jump to the drawing code at a given address to start at a given height and end at a given position (patching the sda with an rts, for instance), but that might work well when using a single scan value for all the column.
That's allmost exactly what the Dbug's weapon does.
He doesn't even have to patch for the rts because he draws the columns by the two sides. he draws one pattern at the top, then one pattern at the botton .. starting from highest and lowest ones and ending with the middle of the screen. So the rts remains at the same place .. its just en entry point adress that is dynamically calculated. It's terribly efficient.

Code: Select all

_DrawColumn
 sta $a000+0,x
 sta $a000+7960,x
 sta $a000+40,x
 sta $a000+7920,x
 sta $a000+80,x
 sta $a000+7880,x
  ....
 rts

Chema wrote:
Sun Nov 15, 2020 9:46 pm
What about patterns? You can have simple patterns or textures and "scale" them with distance (drawing 1 row every n rows when you are far), but that means more code. And, unless the pattern is constant horizontally, you'll need to figure out which column of the graphic is needed. That should not be too difficult as your map may contain not only wall/nowall, but different values for pattern slices. However, this process looks a bit complex (in CPU time) and more difficult to optimize.
I had the idea of using a pattern principle that could allow to:
- create separate texture for different wall
- deal with adaptative darkness depending on the distance

It consists in chaining drawing pattern into cycle based on the number of bit at one.

the chain would be build so that nextPattern[Vn+1] = Vn with nbOfBitSet(Vn) == nbOfBitSet(Vn+1).

the drawing procedure would then look like:

Code: Select all

_DrawColumn
 sta $a000+0,x
 sta $a000+7960,x
 .(:tay: lda _nextPattern,y:.):
 sta $a000+40,x
 sta $a000+7920,x
 .(:tay: lda _nextPattern,y:.):
  ....
 rts
I made an implementation of this approach

https://github.com/jbperin/rewall/tree/changePattern

But I failed to make it work nicely as you can see in this attached TAP file.
WALLS.tap
(7.89 KiB) Downloaded 19 times
Chema wrote:
Sun Nov 15, 2020 9:46 pm
As you can see, I find this quite exciting, so I am eager to learn :)
I don't think I can teach you something. I'm just very glad that this project caught your attention and honoured that you find it impressive. You impressed me so much with your games ..

User avatar
Dbug
Site Admin
Posts: 3506
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: Wolfenstein / DOOM for Oric : has this been done?

Post by Dbug »

jbperin wrote:
Mon Nov 16, 2020 12:44 am
Dbug's ray casting system uses this very smart approach of ray casting which consists in actually shooting a ray until it hits a block.
It's not MY ray casting system. It's just my (not very efficient or accurate) implementation of something that has been around for a decade.
jbperin wrote:
Mon Nov 16, 2020 12:44 am
My first work had been to rework his demo. I speeded it up a bit and start to fix a little bit the stairs effect. I showed my code to Dbug and he didn't feel like making it available on defence-force repository.
And so was it for my own version. It never made it to the shared routines folders because it was not good enough.
I only put on the svn repository what is:
- Runs fast enough
- Relatively free of bugs
- Easy to use or integrate with another program
As long as your version stayed at the cool prototype demo the was no point to add it on the global repository because there was still some serious fish eye distortion problems and it was still not easy to integrate any object in the scene.

jbperin wrote:
Mon Nov 16, 2020 12:44 am
I was very impressed by his principle of filling column by using a patched entry point adress in an unrolled columnn filling routine.
I was also seduced by his idea of actually casting the ray and I still think it is the most efficient approach for tight labyrinths made of block.
As I said casting the ray is not my idea, even Wolfenstein 3D (1992) worked that way.

That being said, for the unrolled STA, it has probably done by other people but I came up with this solution myself.

User avatar
jbperin
Flying Officer
Posts: 178
Joined: Wed Nov 06, 2019 11:00 am
Location: Valence, France

Re: Wolfenstein / DOOM for Oric : has this been done?

Post by jbperin »

Dbug wrote:
Mon Oct 05, 2020 9:16 am
Assuming Jibé manages to get all that stuff together,
I'm starting to put all stuff together : ray casting + glOric + rax engine + mymplayer. It is getting slow but it is not yet optimized. So there remains hope.

https://odysee.com/Oric3dMusic:a


The worrying stuff is that integrating mym player creates unexpected artefact.

Post Reply