IGNORED

# Let's talk 3D graphics

## Recommended Posts

I've made little 3D demo, non programming thread here:

http://atariage.com/forums/topic/237244-rescue-3d-engine-demo

I'd like to discuss programming details here, so it does not offend common users. If you have any question, shoot. I will start by pasting beginning of the discussion from Facebook.

heaven/tqa: are you working with 16bit signed range or with 24bit?

Dr.Sid: Objects are in 8 bits signed, matrices are 8 bits signed. World space is 16 bits (basically object * matrix). This space is used for clipping and projection.
Object position itself however is in 32 bits (might go down to 24, 32 seems to be overkill), and there is process I call subsizing. 16 bits mostly isn't enough for the objects to be both precise enough when close, and small enough (1 pixel) when far. This subsizing process detects if object is beyond 2 bytes, but still close enough to be bigger then 1 pixel. Then it halves both objects size and distance from camera, until it fits. It looks all the same, but can now be done with 16 bits. This transformation is also useful, as it can make objects appear larger, or smaller.
heaven/tqa: yeah.... the subsizing looks interesting... my objects are signed 8bit coords... but engine works in 16bit signed.... and rotation matrix is 16bit, too... but it was hard work to get it done on screen. so I am always interesting in how others have solved the problems... https://www.youtube.com/watch?v=HRvsWijVzNU
Dr.Sid: In my experience 8 bit matrix is enough. That is for rotation only. I don't use matrices extended by position vector, so I only use 3x3 matrix for 3D. And those base vectors are all in -1..1 range. The position itself is added and transformed separately. It is 32 bits first, then subsized to 16, then transformed to world (by inverse camera matrix), which is again 16 (as described above).

heaven/tqa: dont you loose precision?
Dr.Sid: Of course you do. Question is how much. For purpose of your demo (nice filing !) when you only transform the object, and not the camera, I see no problem at all. The most precision sensitive part is camera matrix. Basically you want the camera to be able to turn just so little, that the image shift by 1 pixel. 8bits in just about that, for low resolution display.
Also the precision only affects the representation. I mean: are 8 bits enough to describe the precise direction I want my camera to point at ? There is no precision loss during the transformation itself, because you basically multiply 8 bits of vertex by 8 bits of matrix into 16 bits world. No bits lost = no precision lost.

Edited by Dr.Sid
##### Share on other sites

I've mentioned a few times a few years ago on here that I wrote a 3D engine in 'C' for a PC so I know some things about all this. I've not done this on an 8-bit machine before though.

Do you wish to keep the demo in wireframe or do you wish to move to filled polygons? There's upsides and downsides with both of course, speed being the main one.

I may be able to dig out some old code for filled polygons (in 'C') if you like (though it will be difficult to locate). I remember that it involved splitting everything into triangles and every triangle either had a flat top or a flat bottom. I was using integer mathematics, though at a higher precision than on the Atari. Though I can see that you can use Heaven's closer work as an inspiration due to it being on the A8. Don't forget the people who did the "Control" demo with a 3D world with filled polygons.

If you did filled polygons, you would also need to consider back face culling to speed up the process.

How are you determining if an object needs drawing? Are you using a viewport of some kind?

Linked lists are also very useful in 3d programming.

How do you sequence your demo? Do you have a pseudo-language coded? That'd be a bit like a music tracker but for 3D scenery.

Edited by snicklin
##### Share on other sites

Great work Dr.Sid ! Looks great.

As Snicklin said, I would love to see filled polygon version also. Back face culling would reduce number of polygons to draw and eor-filler could make transition easier (no need to draw polys, just lines and eor-filler).

Most important - wish you good motivation and good times spent coding this!

##### Share on other sites

my backface culling was not so trivial... but worked in the end... but only works with transformed triangles. Not sure if you work with triangles at all?

##### Share on other sites

I did not think much about filling. So far I can't see how it could be fast enough. Even the lines are so so.

Also filling means backface culling, as you mentioned. Culling itself is not that hard or slow.

But it means you will either only work with convex objects only (like Elite). But then it will simply look like Elite, cause Braben basically used all possible convex shapes :-) Good thing is you can use convex objects backface culling with wireframe too (again, as Elite does).

Or you can use non-convex objects. Then there is some more things to compute, but again, it's doable, and not that complex, I did it on Amiga. I had all objecst split into convex subobjects, ordered in binary tree where in every node there was plane which divided the object. As you draw, you just detected orientation of the plane, and based on that you decided which subtre to draw first, and which second.

But it means you will fill polygons over already filled polygons. And speed goes down again.

Also non-convex with backface culling cannot be easily used with wireframe, as sometimes only part of the edge is visible.

Of course this all affects how you store your models, you need faces to both filling and back-culling .. for wireframe you only need edges.

So at the moment I only plan to work with wires, more Mercenary look then Elite look. Also I think it has it's magic, especially for space kinda game.

##### Share on other sites

I like the wires. Overall, this looked fluid enough to be interesting. Sometimes, a simple, open kind of world can be immersive when the story or action is compelling.

##### Share on other sites

As for the sequence .. all the state is in the objects themself, including rotation and speed. For objects I only use local speed, so when I set speed for object and rotation, it will follow curve. All the 'screenplay' language does it 'pokes' speed, rotation, and things into objects, animation engine does the rest.

There is also option for camera to follow any object, and commands for printing the messages and waiting.

Synchronizing with music is done simply by TV frames. Music runs in VBI (it's RMT player), my song has speed 9 VBIs per tracker line. So if I want to wait let's say 32 track lines, I wait 32x9 VBIs.

The commands for changing object use last added object, or there is command for selecting other object.

Here is short example right from the start of the animation:

SceneReset
SceneWait 16*9

;ship enter 16 ---------------------
SetPos -20,1,0
SetRotation 0,0,-15
SetSpeed 0,0,1200

SceneWait 4*9
SetRotation 0,0,0
SceneWait 12*9

;ship flyby 48 ---------------------
SceneReset
SetPos -100,0,0
SetRotation 0,0,-4
SetSpeed 0,0,1000

SetCameraPos 0,5,-20
SetCameraObject Transport
SceneWait 16*9
SetRotation 0,0,0
SceneCls color_ship
ScenePrint " OK12 to OC1: I have exited hyperspace "
ScenePrint " and request high parking orbit .. "
SceneWait 32*9

Btw. SetRotation sets rotation speed, only way to set which way the object is turned in the beginning is SetHeading.

##### Share on other sites

I like the wires. Overall, this looked fluid enough to be interesting. Sometimes, a simple, open kind of world can be immersive when the story or action is compelling.

Agreed. Anyone played Moonfall on C64 ? (Amiga version was good, but nothing spectacular. C64 version was really one of rare, good games).

Wireframe, no real 3d (just horizontal rotation, up-down + speed....), but so much content, trade, fighting, weather, radar....

Couldn't stop playing until you owned whole planet

##### Share on other sites

@"Screenplay language" and pro-wireframe: Great idea, love the implementation. Good point on wireframe 'freedom'. Makes you focus on gameplay instead of cool looking game.

Doesn't mean we don't want wing commander on A8

##### Share on other sites

Agreed. Anyone played Moonfall on C64 ? (Amiga version was good, but nothing spectacular. C64 version was really one of rare, good games).

Wireframe, no real 3d (just horizontal rotation, up-down + speed....), but so much content, trade, fighting, weather, radar....

Couldn't stop playing until you owned whole planet

Wow .. never heard about Moonfall. Looks very cool and it seem to have lots of features I want to have ! Now where did put that C64 emulator ..

##### Share on other sites

Our fractal and own researches show that eor filler is not that time consuming. Check profiler in Altirra and most time is spend 3d calcs.

I still be leave your engine needs 16bit internal through the render pipeline to implement things like subpixel accuracy

##### Share on other sites

SceneReset

SceneWait 16*9

;ship enter 16 ---------------------

...

As you have this pseudo-language for controlling the scenes/objects, each command could be assigned a code...

i.e.

SceneReset=0

SceneWait=2

...

and then you can load new data into a buffer in order to have longer animations.

You would need a jump table for each command to jump to the actual command.

Edited by snicklin
##### Share on other sites

Wow, this is really good. Years back when I was really programming the Atari I done most things, but 3D graphic manipulation was 1 of the few things I didn't get round to understanding, it was next on my list until that is circumstances took me away from the Atari. I would love to see the 3D engine source code. Out of curiosity what are the algorythms (or mathematical functions) for calculating the Z co-ordinate.

I have at the moment recently got round to programming a routine to move text around on a mode 8 screen through various patterns for a demo, but I ain't going to finish that until I finish the current project I'm doing, of which is a text adventure engine, and although I've progressed fairly well, this is still going to take some time to finish.

##### Share on other sites

Well those are not actually commands, but just numbers, as you said. I use macros for them so I can more easily write the code, but SceneReset is just zero, AddObject is 1 followed by object pointer, and so on. So yes, it would be quite simple to load animations from disc. But then cutscenes are not the most important thing in the game. I'm not sure if I will keep this code for the game itself (whatever game it may be).

As you have this pseudo-language for controlling the scenes/objects, each command could be assigned a code...

i.e.

SceneReset=0

SceneWait=2

...

and then you can load new data into a buffer in order to have longer animations.

You would need a jump table for each command to jump to the actual command.

##### Share on other sites

Wow, this is really good. Years back when I was really programming the Atari I done most things, but 3D graphic manipulation was 1 of the few things I didn't get round to understanding, it was next on my list until that is circumstances took me away from the Atari. I would love to see the 3D engine source code. Out of curiosity what are the algorythms (or mathematical functions) for calculating the Z co-ordinate.

I have at the moment recently got round to programming a routine to move text around on a mode 8 screen through various patterns for a demo, but I ain't going to finish that until I finish the current project I'm doing, of which is a text adventure engine, and although I've progressed fairly well, this is still going to take some time to finish.

I'm not sure if I can make it clear for anyone, but I will start with something and then we can focus on anything not clear.

I use matrices for representing camera and objects rotation (not angles). I multiply object matrix and inverse camera matrix to get so called model-view matrix. That transforms vertex coordinates from object space right into camera space. So transformation of 1 point is just 3 axis vector multiplied with 3x3 matrix.

After this I do clipping with viewport. I use 90 degrees view angle, so limits of what I can see are simply planes of X=Z, -X=Z, Y=Z and Y=-Z. That simplifies clipping a bit.

Perspective transformation is also simpler because of 90 degrees view angle, it's just x = X/Z, y = Y/Z.

Edited by Dr.Sid
##### Share on other sites

As you are making a game for this, I see that this is quite different from doing a demo.

As for a game idea..., I see that you have your wife at home. Perhaps you need to bring some things back to her? Do some intergalactic trading until you can get a diamond ring?

Or perhaps you can trade for money for fuel to take her to another planet for fertility treatment, then you have some 8-bit fun with her and then she gives birth to octuplets? :)

I dunno, just a daft idea for an amusing game.

##### Share on other sites

Nice shortcut on the 90 degree view angle. Seems to work out well too.

Here's a rundown on the various things just discussed.

http://www.codinglabs.net/article_world_view_projection_matrix.aspx

I've got a familiarity with this from an entirely different perspective. (robotics, CAD, etc...) It's the same sorts of math.

Honestly, I'm kind of impressed so few bits actually worked out well. Nicely done so far!

A while back, I toyed with doing something like this on the little micro I program on from time to time. Might be some nice shortcuts and optimizations here over time.

##### Share on other sites

here is profiler view of my engine...

and the source code... feel free to ask... the source is not much optimised as it was ment to be a compo filler at Revision 2015 party.

some notes...

the rotation matrix, coords all are 16bit signed same with ztab factor table for the transformation. that's why it uses 32bit signed multiplication which is expensive.

it was to ment to use 16bit through the complete render engine because 16bit accurancy (even sintables) make sure that it will look smooth not only for rotation and moving but next thing on my list was sub-pixel accurancy rendering.

the actual poly fill routine is still based on the work of Probe (thx mate) and was found in one of his 1k demos at the Atari source code archive. the only what is left from that code is the hline inner loop which does the line pixel drawing from left to right and is sitting in ZP.

screen architecture helped in clipping (how?)...

I am using 256 byte scanlines. so I can place sever screens next to each others... so i have some unseen pixels left/right per visible screen.

so... its basicly vram-buffer left, vram1, vram-buffer-right, vram2, vram2-buffer right... same some buffer-lines top/bottom of visible screen

So clipping is only done "visible" not in maths ANTIC makes it possible... C64 would suffer.

Popmilo and Oswald and me were discussing similar techniques when we were developing our Rescue of Fractalus experiments. Lucasfilm was using this "flip screen" method which is quite handy. why?

you can simply index to the desired screen:

fex. LDX #39, LDA #0, STA VRAM, STA VRAM+40,X .... DEX

to clear vram1 and with LDX #79 to index into VRAM2... same with plot routine, EOR fillers etc. quite compact in code and not so massive in ram footprint when unrolling only rows instead of 40x96 or 40x192 bytes.

in the Fractal experiments and profiler view it showed that actually the CLR screen routines are not the bottle neck but mainly the 3d calcs are... so I did not spend too much in that. Experiments showed that unrolling complete clr screen loop showed speed gain of around 5-10% which is not as much when you spending 90% in 3d calcs

having 256 byte scanlines no need to tell you the advantages-adressing pixel adress (x/2+y*256).

here in the demo clr screen simply copies background pic into the buffers. Only optimising I was thinking here is that you need only to copy the lines which were actually covered by the object... but again first experiments showed that controlling the lines which were covered and all the logic behind it might not gain that speed. it would gain in a higher resolution but not in my 80x74 resolution I was working here... thank to the 1,77 MHz .

another issue which people should be aware off when doing 3d... DMA penalty by Antic... (yeah... you will hit same issues even on Amiga with it's copper/blitter Jay Miner spirit ).

in some other project I gained 1-2 frames faster rendering with the VSCROLL trick or much simpler... the old "leave every 2nd scanline out" thing... I told Axis of Oxyron and he did same thing on the Amiga and his latest Demo esp. in the Voxel HAM6 scene there.

the "2nd blank lines" oldschool trick is

\$4f,vram lo,vram hi

\$00

\$4f,vram lo,vram hi

\$00
\$0f ;vram+40

\$4f,vram+40 lo,vram+40 hi

\$00
\$0f ;vram+80
...
just my 2 cents...
or you are using GR. 7 best for 3d on Atari though

ars3_announcement_3_public.asm

Edited by Heaven/TQA
##### Share on other sites

Thanks for that!

I'm going to give a nice long read. Really appreciated.

Heh

Input:

Output:

Clobbered:

Nice, to the point, clean.

##### Share on other sites

So, you save multiplies during the scene by transforming directly to the screen, and then perform that same operation again during a camera move. Seems to me, this is faster overall, not just when the camera isn't moving. Is that true?

##### Share on other sites

... All the 'screenplay' language does it 'pokes' speed, rotation, and things into objects, animation engine does the rest.

There is also option for camera to follow any object, and commands for printing the messages and waiting.

Synchronizing with music is done simply by TV frames. Music runs in VBI (it's RMT player), my song has speed 9 VBIs per tracker line. So if I want to wait let's say 32 track lines, I wait 32x9 VBIs.

The commands for changing object use last added object, or there is command for selecting other object.

Here is short example right from the start of the animation:

SceneReset

SceneWait 16*9

;ship enter 16 ---------------------

SetPos -20,1,0

SetRotation 0,0,-15

SetSpeed 0,0,1200

SceneWait 4*9

SetRotation 0,0,0

SceneWait 12*9

;ship flyby 48 ---------------------

SceneReset

SetPos -100,0,0

SetRotation 0,0,-4

SetSpeed 0,0,1000

SetCameraPos 0,5,-20

SetCameraObject Transport

SceneWait 16*9

SetRotation 0,0,0

SceneCls color_ship

ScenePrint " OK12 to OC1: I have exited hyperspace "

ScenePrint " and request high parking orbit .. "

SceneWait 32*9

Btw. SetRotation sets rotation speed, only way to set which way the object is turned in the beginning is SetHeading.

To me, this looks like you are re-inventing VRML. Which leads to this question: "Why not just implement a localized VRML for the Atari?".

VRML was a really well-thought-out language for 3D world, object & scene manipulation, and it was very well documented. There were 3D graphics programs that would let you export VRML compliant objects, and it was an awesome tool.

It was an awesome tool... until extreme-feature-creep, a name-change, and the marketing people & journalists helped to screw it all up (calling it "Vermil", like "Vermin", instead of "V. R. M. L.", etc.)... However, if someone were to implement VRML 1.0 or VRML 2.0 on the Atari, then you would be providing a tool that people could use to make demos, games, or add 3D into any program, quite easily. Actually, I'm almost surprised that at least a subset of VRML was never written for the Atari. Would be a cool thing.

##### Share on other sites

Well, VRML is a very significant expansion over the simple macros he's got here. Just parsing the average file, handling the transforms and displaying ANYTHING would very likely exceed the RAM on most Ataris, and the compute requirements would be insane. Like, try it, "wait a day" and see if stuff shows up. Maybe not that bad, but not interactive either, IMHO.

##### Share on other sites

Well, VRML is a very significant expansion over the simple macros he's got here. Just parsing the average file, handling the transforms and displaying ANYTHING would very likely exceed the RAM on most Ataris, and the compute requirements would be insane. Like, try it, "wait a day" and see if stuff shows up. Maybe not that bad, but not interactive either, IMHO.

What you say is true, if you are looking at trying to parse complicated pre-existing worlds, in real time, but if you look at it from the perspective of having some kind of Universal Tool for 3D on the Atari, VRML makes a lot of sense. During the time that it was called VRML it was a very slim and manageable language, not like the behemoth that it later became. Anyone can buy an old book on VRML, from Amazon... Why re-invent a way to do something that had the best minds in the business (at the time) originally author it, in the first place?

For example, just making the current commands of the "3D Screenplay Language" compatible with VRML syntax, with regard to arguments & parameters, would be a good start. Making the object matrix data conform with VRML specifications would allow lots of extremely simple objects to be made in a 3D modeling program, on a modern system, objects which could then be exported, to be used on the Atari. This would save a lot of time when making demos.

I would say that it would be a good thing to use the "Chip Away Approach"... start by just focusing on the syntax, getting the current syntax to be VRML compliant, then slowly adding ideas that have already been fleshed-out in the VRML spec. Basically, start small. VRML was really well thought out, with regard to manipulating 3D with low system resources. Even a tiny subset of VRML 1.0 would be better than a whole new, fully undocumented approach.

The other thing to consider is that Atari expansion hardware, and emulated expansion hardware is getting better & better. This is a really good use for the Veronica hardware, could make great use of VBXE, and RAM expansion... & as usual, it does take software to sell hardware, or to at at least to try things out, in an emulator.

I'm just trying to point out that the VRML spec exists, and could be used to great effect with this project.

##### Share on other sites

I would flip the problem and make a filter to transform simple VRML into this limited space.

##### Share on other sites

I would flip the problem and make a filter to transform simple VRML into this limited space.

I would agree, if it was further along, and if we had no access to the developer or source code... but since it's still brandy-new, why not just build a strong foundation that has a clear plan for the future?

Then again, it's all up to what user Dr. Sid wants to do... sometimes a little bit of planning can go a long way. Just little things, like ensuring compatible world & object co-ordinate systems, definitions of object matrices, primitives, transforms, translation paths, & methods of text display could probably be made reasonably compatible with VRML spec, in one night of coffee-fueled-coding, since he already has the basics of what is needed to manipulate 3D environments.

It is mostly just a matter of defining a standard API to the existing 3D engine, specifically to make things less squirrelly in the future. As I said, though, it's all up to Dr. Sid, he's the one coding it... I'm just looking down the road of the Software Lifecycle, and trying to offer suggestions to make things easier, down that road.

Aside from all of that, I'm happy that he had the foresight to design the "3D Screenplay Language" (3DSL) into it, in the first place.

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.