New demo uploaded: 3d wire frame animated spaceship
-
- Posts: 292
- Joined: Wed Jun 03, 2020 11:33 am
- Location: Kalmar, Sweden
New demo uploaded: 3d wire frame animated spaceship
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.
- desertfish
- Posts: 1088
- Joined: Tue Aug 25, 2020 8:27 pm
- Location: Netherlands
New demo uploaded: 3d wire frame animated spaceship
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.
- desertfish
- Posts: 1088
- Joined: Tue Aug 25, 2020 8:27 pm
- Location: Netherlands
New demo uploaded: 3d wire frame animated spaceship
New version available, here we go, hidden line removal based on that simple surface normal discussed above:
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)
New demo uploaded: 3d wire frame animated spaceship
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
New demo uploaded: 3d wire frame animated spaceship
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.
- desertfish
- Posts: 1088
- Joined: Tue Aug 25, 2020 8:27 pm
- Location: Netherlands
New demo uploaded: 3d wire frame animated spaceship
I am really considering now to port it to X16 ... It is still a huge endeavour ... but it is getting possible now.
New demo uploaded: 3d wire frame animated spaceship
Wow - that would be HUGE ?!