New demo uploaded: 3d wire frame animated spaceship

All aspects of programming on the Commander X16.
Johan Kårlin
Posts: 292
Joined: Wed Jun 03, 2020 11:33 am
Location: Kalmar, Sweden

New demo uploaded: 3d wire frame animated spaceship

Post by Johan Kårlin »

I remember doing this on the Amiga a long time ago. I had great help by the book "Atari ST 3D Graphichs Programming" (https://archive.org/details/Atari_ST-3D_Graphics_Programming/mode/2up). Of course, the programming examples are in 68000 assembler but there are also lengthy explanations of concepts and methods. If you are familiar with linear algebra, it really helps. When it comes to hidden line removal, a method that is discussed in the book is to calculate the normal vector of each plane (polygon). If the vector points towards the viewer, the plane is visible, if it points away from the viewer, the plane is hidden. The limitation is that this only works on convex bodies. (On concave bodies planes can be partially visible.) If you ever wondered why all ships in Elite are convex bodies I bet it is because this method is used : ). Another method is to simply sort the planes and then draw the furthest plane first and the closest last. It works well on for example mathematically rendered 3D landscapes where it makes sense of talking of the planes as positioned in a specific order. If I take a guess, this is the method the game "Virus" used. 
User avatar
desertfish
Posts: 1097
Joined: Tue Aug 25, 2020 8:27 pm
Location: Netherlands

New demo uploaded: 3d wire frame animated spaceship

Post by desertfish »


Yeah the surface normal method is what I experimented with in my Python prototype shown above. It works fairly well and is quite cheap to do however it's not entirely accurate in the simplified version that I came up with.  I only check of the Z component is negative or positive and it works "most of the time" but fails for some polygons that are perspective projected.  I think it's acceptable though at least for a first solution!

As I'm only drawing lines not full surfaces the painter algorithm (back-to-front drawing) can't be used I think.

User avatar
desertfish
Posts: 1097
Joined: Tue Aug 25, 2020 8:27 pm
Location: Netherlands

New demo uploaded: 3d wire frame animated spaceship

Post by desertfish »


New version available, here we go,  hidden line removal based on that simple surface normal discussed above:

image.png.2f0df4ad3b0d2e3a4585a9b76b42df6b.png

 

Adding more ships to the program and making a slide show of them is currently not possible due to programming language limitations of Prog8, unfortunately (everything has to be statically allocated)

SerErris
Posts: 172
Joined: Sat Aug 08, 2020 9:18 am

New demo uploaded: 3d wire frame animated spaceship

Post by SerErris »


Actually there was some recent and monumental work on documenting the original assembler of the BBC ELITE. The great stuff is, the BBC computer had a 6502 as well and all the MATH code and all the graphics code could be reused simply.

Obviously the draw routines need rework (e.g. the screen setup and output) and the sound as well. But if you ignore sound for now, and adapt the draw routines for the Vera, it should be possible to get the start screen working - e.g. your spinning ship with line removal ?

This is two masterpieces .. the longer I look at the Elite Source code ... wow ... and those guys were still in school or university at that time. And the comments is another masterpiece. I never have seen a better commented source code with actual explanations on how the engine worked. That includes all the math routines, how the backface culling works and alot of that stuff. It also completely explains the main game loop, how it works and so you can learn a lot by reading this.

The commenting has been done by Mark Moxon (of cause with a lot of help by others).

https://raw.githubusercontent.com/markmoxon/elite-beebasm/master/sources/elite-source.asm

This is the original definition of a MK3 btw:

 


Quote




\ ******************************************************************************

\

\       Name: SHIP5

\       Type: Variable

\   Category: Drawing ships

\    Summary: Ship blueprint for a Cobra Mk III

\

\ ******************************************************************************



.SHIP5



 EQUB 3                 \ Max. canisters on demise = 3

 EQUW 95 * 95           \ Targetable area          = 95 * 95

 EQUB &BC               \ Edges data offset (low)  = &00BC

 EQUB &54               \ Faces data offset (low)  = &0154

 EQUB 153               \ Max. edge count          = (153 - 1) / 4 = 38

 EQUB 84                \ Gun vertex               = 84 / 4 = 21

 EQUB 42                \ Explosion count          = 9, as (4 * n) + 6 = 42

 EQUB 168               \ Number of vertices       = 168 / 6 = 28

 EQUB 38                \ Number of edges          = 38

 EQUW 0                 \ Bounty                   = 0

 EQUB 52                \ Number of faces          = 52 / 4 = 13

 EQUB 50                \ Visibility distance      = 50

 EQUB 150               \ Max. energy              = 150

 EQUB 28                \ Max. speed               = 28

 EQUB &00               \ Edges data offset (high) = &00BC

 EQUB &01               \ Faces data offset (high) = &0154

 EQUB 1                 \ Normals are scaled by    = 2^1 = 2

 EQUB %00010011         \ Laser power              = 2

                        \ Missiles                 = 3



\VERTEX    x,    y,    z, face1, face2, face3, face4, visibility

 VERTEX   32,    0,   76,    15,     15,   15,    15,         31    \ Vertex 0

 VERTEX  -32,    0,   76,    15,     15,   15,    15,         31    \ Vertex 1

 VERTEX    0,   26,   24,    15,     15,   15,    15,         31    \ Vertex 2

 VERTEX -120,   -3,   -8,     3,      7,   10,    10,         31    \ Vertex 3

 VERTEX  120,   -3,   -8,     4,      8,   12,    12,         31    \ Vertex 4

 VERTEX  -88,   16,  -40,    15,     15,   15,    15,         31    \ Vertex 5

 VERTEX   88,   16,  -40,    15,     15,   15,    15,         31    \ Vertex 6

 VERTEX  128,   -8,  -40,     8,      9,   12,    12,         31    \ Vertex 7

 VERTEX -128,   -8,  -40,     7,      9,   10,    10,         31    \ Vertex 8

 VERTEX    0,   26,  -40,     5,      6,    9,     9,         31    \ Vertex 9

 VERTEX  -32,  -24,  -40,     9,     10,   11,    11,         31    \ Vertex 10

 VERTEX   32,  -24,  -40,     9,     11,   12,    12,         31    \ Vertex 11

 VERTEX  -36,    8,  -40,     9,      9,    9,     9,         20    \ Vertex 12

 VERTEX   -8,   12,  -40,     9,      9,    9,     9,         20    \ Vertex 13

 VERTEX    8,   12,  -40,     9,      9,    9,     9,         20    \ Vertex 14

 VERTEX   36,    8,  -40,     9,      9,    9,     9,         20    \ Vertex 15

 VERTEX   36,  -12,  -40,     9,      9,    9,     9,         20    \ Vertex 16

 VERTEX    8,  -16,  -40,     9,      9,    9,     9,         20    \ Vertex 17

 VERTEX   -8,  -16,  -40,     9,      9,    9,     9,         20    \ Vertex 18

 VERTEX  -36,  -12,  -40,     9,      9,    9,     9,         20    \ Vertex 19

 VERTEX    0,    0,   76,     0,     11,   11,    11,          6    \ Vertex 20

 VERTEX    0,    0,   90,     0,     11,   11,    11,         31    \ Vertex 21

 VERTEX  -80,   -6,  -40,     9,      9,    9,     9,          8    \ Vertex 22

 VERTEX  -80,    6,  -40,     9,      9,    9,     9,          8    \ Vertex 23

 VERTEX  -88,    0,  -40,     9,      9,    9,     9,          6    \ Vertex 24

 VERTEX   80,    6,  -40,     9,      9,    9,     9,          8    \ Vertex 25

 VERTEX   88,    0,  -40,     9,      9,    9,     9,          6    \ Vertex 26

 VERTEX   80,   -6,  -40,     9,      9,    9,     9,          8    \ Vertex 27



\EDGE vertex1, vertex2, face1, face2, visibility

 EDGE       0,       1,     0,    11,         31    \ Edge 0

 EDGE       0,       4,     4,    12,         31    \ Edge 1

 EDGE       1,       3,     3,    10,         31    \ Edge 2

 EDGE       3,       8,     7,    10,         31    \ Edge 3

 EDGE       4,       7,     8,    12,         31    \ Edge 4

 EDGE       6,       7,     8,     9,         31    \ Edge 5

 EDGE       6,       9,     6,     9,         31    \ Edge 6

 EDGE       5,       9,     5,     9,         31    \ Edge 7

 EDGE       5,       8,     7,     9,         31    \ Edge 8

 EDGE       2,       5,     1,     5,         31    \ Edge 9

 EDGE       2,       6,     2,     6,         31    \ Edge 10

 EDGE       3,       5,     3,     7,         31    \ Edge 11

 EDGE       4,       6,     4,     8,         31    \ Edge 12

 EDGE       1,       2,     0,     1,         31    \ Edge 13

 EDGE       0,       2,     0,     2,         31    \ Edge 14

 EDGE       8,      10,     9,    10,         31    \ Edge 15

 EDGE      10,      11,     9,    11,         31    \ Edge 16

 EDGE       7,      11,     9,    12,         31    \ Edge 17

 EDGE       1,      10,    10,    11,         31    \ Edge 18

 EDGE       0,      11,    11,    12,         31    \ Edge 19

 EDGE       1,       5,     1,     3,         29    \ Edge 20

 EDGE       0,       6,     2,     4,         29    \ Edge 21

 EDGE      20,      21,     0,    11,          6    \ Edge 22

 EDGE      12,      13,     9,     9,         20    \ Edge 23

 EDGE      18,      19,     9,     9,         20    \ Edge 24

 EDGE      14,      15,     9,     9,         20    \ Edge 25

 EDGE      16,      17,     9,     9,         20    \ Edge 26

 EDGE      15,      16,     9,     9,         19    \ Edge 27

 EDGE      14,      17,     9,     9,         17    \ Edge 28

 EDGE      13,      18,     9,     9,         19    \ Edge 29

 EDGE      12,      19,     9,     9,         19    \ Edge 30

 EDGE       2,       9,     5,     6,         30    \ Edge 31

 EDGE      22,      24,     9,     9,          6    \ Edge 32

 EDGE      23,      24,     9,     9,          6    \ Edge 33

 EDGE      22,      23,     9,     9,          8    \ Edge 34

 EDGE      25,      26,     9,     9,          6    \ Edge 35

 EDGE      26,      27,     9,     9,          6    \ Edge 36

 EDGE      25,      27,     9,     9,          8    \ Edge 37



\FACE normal_x, normal_y, normal_z, visibility

 FACE        0,       62,       31,         31    \ Face 0

 FACE      -18,       55,       16,         31    \ Face 1

 FACE       18,       55,       16,         31    \ Face 2

 FACE      -16,       52,       14,         31    \ Face 3

 FACE       16,       52,       14,         31    \ Face 4

 FACE      -14,       47,        0,         31    \ Face 5

 FACE       14,       47,        0,         31    \ Face 6

 FACE      -61,      102,        0,         31    \ Face 7

 FACE       61,      102,        0,         31    \ Face 8

 FACE        0,        0,      -80,         31    \ Face 9

 FACE       -7,      -42,        9,         31    \ Face 10

 FACE        0,      -30,        6,         31    \ Face 11

 FACE        7,      -42,        9,         31    \ Face 12



 

SerErris
Posts: 172
Joined: Sat Aug 08, 2020 9:18 am

New demo uploaded: 3d wire frame animated spaceship

Post by SerErris »



On 9/18/2020 at 10:29 AM, desertfish said:




Yeah the surface normal method is what I experimented with in my Python prototype shown above. It works fairly well and is quite cheap to do however it's not entirely accurate in the simplified version that I came up with.  I only check of the Z component is negative or positive and it works "most of the time" but fails for some polygons that are perspective projected.  I think it's acceptable though at least for a first solution!



As I'm only drawing lines not full surfaces the painter algorithm (back-to-front drawing) can't be used I think.



This is what Ian Bell and David Braben created (explained by Mark)


Quote




\ ******************************************************************************

\

\       Name: LL9 (Part 5 of 11)

\       Type: Subroutine

\   Category: Drawing ships

\    Summary: Draw ship: Calculate the visibility of each of the ship's faces

\

\ ******************************************************************************

\

\ Deep dive: Back-face culling

\ ============================

\

\ One of the reasons that Elite's 3D wireframe ships look so good is because

\ you can't see through them - they look genuinely solid. This is down to a

\ process called "back-face culling", a mathematical process that works out

\ which faces of the ship are visible to the viewer and which ones aren't. It

\ then discards (or "culls") any faces that aren't visible and only draws those

\ that we can actually see. This prevents the wireframes from being see-through,

\ and this gives the ships a real sense of solidity.

\

\ The main principle behind back-face culling is the dot product. This simple

\ mathematical operation takes two vectors and produces a scalar value that is

\ in essence a kind of mathematical application of one vector to the other, of

\ taking the "essence" of one vector and applying it to another. For the

\ purposes of back-face culling in Elite, we use the dot product in two distinct

\ ways.



This is just the summary, In the source is following long and long discussion on the details of that. 

User avatar
desertfish
Posts: 1097
Joined: Tue Aug 25, 2020 8:27 pm
Location: Netherlands

New demo uploaded: 3d wire frame animated spaceship

Post by desertfish »


@SerErris WOW thanks for this info I had not discovered the annotated source code yet, incredible

SerErris
Posts: 172
Joined: Sat Aug 08, 2020 9:18 am

New demo uploaded: 3d wire frame animated spaceship

Post by SerErris »


I am really considering now to port it to X16 ... It is still a huge endeavour ... but it is getting possible now.

User avatar
AndyMt
Posts: 326
Joined: Sun Jun 21, 2020 3:02 pm
Location: Switzerland

New demo uploaded: 3d wire frame animated spaceship

Post by AndyMt »


Wow - that would be HUGE ?!

Post Reply