Author Topic: Descent 68k/X3D  (Read 26973 times)

0 Members and 1 Guest are viewing this topic.

Offline catastropher

  • LV2 Member (Next: 40)
  • **
  • Posts: 30
  • Rating: +11/-0
    • View Profile
Descent 68k/X3D
« on: March 15, 2015, 05:05:49 am »
Edit: I updated the binaries to use the new improvements. Download link at the bottom of the post!

Way back in 2011, my step mom found her old TI92+, which she generously gave to me. I was in 10th grade at the time and had only done Z80 ASM programming, so naturally I really really wanted to learn to program the 68k calculators. Can you guess what the first program I tried to make was? Descent! Being totally inexperienced in 3D programming however, my first few attempts failed miserably. Since I did post-secondary and started college full time in 11th grade, I naturally decided that programming the calculator was my top priority; thus I invested significant time during my freshmen year into learning it! ;D

The result of my first 3D attempt in 2011 wasn't that impressive, but I got a 3D wireframe cube of triangles to spin:



Over the next few years, I experimented quite a bit with 3D programming. In sophomore year, I managed to implement a segment buffer for hidden surface removal. In junior year, I finally began to understand 3D math. I began work on X3D, a knock up engine that rendered 3D graphics as if it were rendering on a TI83+.

Let's flash forward to last month. Since I'm a senior, I had to pick a capstone project for my Senior Seminar class. At first I wasn't going to do anything calculator related because, quite honestly, I hadn't even turned my TI92+ on in several months. But then, when I was teaching my little brother some programming, he noticed my calculator in my desk drawer and I was hit with a wave a nostalgia - I knew that I wanted to start working on X3D-68k again. That night in February, I stayed up into the wee hours of the night and managed to produce this from scratch:



So, I got thinking: if I could look at the cubes from the outside, wouldn't flipping the normals let me view the cube from the inside? While this did totally work, the calculator just could not cope with drawing grayscale triangles that filled the whole screen, even after clipping (the framerate dropped to under 6 fps). Unfortunately, because of this, I had no choice but to rewrite the engine to do monochrome rendering  :(

So, I did indeed rewrite it. My first approach was to draw white triangles and outline them. However, I got thinking again: levels in Descent are made out of interconnected "cubes" (really convex octahedrons) that share a single face. In portal rendering, this is know as a "portal". Thus, the only way to see the cube on the other side is through that portal. If I just set the clipping region to be that shared face, I can draw the level polygons in any order since the cubes are convex! Even better, because there is zero overdraw, I don't need to actually rasterize the triangles, just draw the outline of them (since it's monochrome)!

Two weeks ago, I found out that too much speed coding and not enough code maintenance was starting to catch up with me. Worse, it turns out that when you do 2D portal rendering, you start getting singularities and weird geometry when part of the portal is off screen. Thus, I rewrote the engine for the final time to have a well maintained code base, and a 3D polygon clipper/view frustum clipping. As of today (well really yesterday since I'm writing this at 4:00 AM here), I finally fixed all weird clipping issues that I've been running into! After three years, I feel like I finally have something that shows some actual progress!  :)

So, here are features of X3D so far:
  • Levels made of interconnected cubes. They can be stretched, skewed, rotated, etc. so long as they remain convex.
  • 3D portal rendering. If the portal isn't visible, nothing on the other side of the portal can be visible so it's culled.
  • 2D/3D clipping to the viewing frustum.
  • Collision detection with the level cubes.
  • Two axes of rotation (you can look up, down, left, and right). The camera moves in the direction you're facing.

Here are some screenshots of the rendering output. Note that even though the engine supports more complex shapes than actual cubes, I was lazy so I threw a quick, small level together out of them:







So, the "Line count" tells you the number of lines the render had to draw in a given frame. Woah, that number is ridiculously high! Every cube has 12 edges, and each edge is shared between two faces. Since the renderer currently works by drawing individual faces, an edge will wind up being drawn twice. Worse, if two cubes are connected, they share 4 edges - each one of those edges will then wind up getting draw 4 times! Also, this leads to some lines looking thicker than others: if one of the edges is off by even a pixel the lines will diverge slightly. Luckily, I have already devised an algorithm to prevent this and am working on implementing it now. So, until then, the engine runs a bit slow because in worst case, it's doing 4 times as much work than it needs to This issue has now been fixed!

Anyway, since this is a school project, I can't release the source code until after I present it at the senior symposium (sometime in April). I can, however, release the binaries for you to try! Disclaimer: there is a very high chance of this crashing your calculator! I am not responsible for any damage caused by running it! That aside, there shouldn't be too many problems while running it, though visual artifacts are likely because I'm still debugging it. If it crashes with an error message, please pm/email me with the error message! Thanks! Note that I only have a TI92+; I tried it on a TI89 Titanium using TiEmu and it seemed to work just fine, but I have no way to verify if it works on a real calc yet. Here are the keys:

Up/down: turn up and down
Left/right: turn left and right
F1/F2: move forward/backward
F3/F4: straife left/right
Hold enter: display position, angles, and current cube
Esc: quit

If I can get the renderer working fast enough, I most certainly want to turn this into a game of Descent (though this may take quite a while until completion). Thanks for reading and I'll post any progress that I make!
« Last Edit: March 17, 2015, 03:30:37 pm by catastropher »

Offline Sorunome

  • Fox Fox Fox Fox Fox Fox Fox!
  • Support Staff
  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 7920
  • Rating: +374/-13
  • Derpy Hooves
    • View Profile
    • My website! (You might lose the game)
Re: Descent 68k/X3D
« Reply #1 on: March 15, 2015, 05:45:28 am »
Wha, that is some quite big post! All I can say that 3D development has always amazed me, and you definitely managed to get some nice things running! Also it's good to see some 68k development again!
I wish you good luck with your project and hope it turns out to become a complete game! :D

THE GAME
Also, check out my website
If OmnomIRC is screwed up, blame me!
Click here to give me an internet!

Offline catastropher

  • LV2 Member (Next: 40)
  • **
  • Posts: 30
  • Rating: +11/-0
    • View Profile
Re: Descent 68k/X3D
« Reply #2 on: March 15, 2015, 11:51:29 am »
@Sorunome, thank you so much for the kind words! :) And yeah, it's quite a big post! haha I've really wanted to do this for a long time, so hopefully I'll be able to turn it into a full game. I just hope there will be at least a few people who still have a 68k calc left to play it!

Offline pimathbrainiac

  • Occasionally I make projects
  • Members
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1731
  • Rating: +136/-23
  • dagaem
    • View Profile
Re: Descent 68k/X3D
« Reply #3 on: March 15, 2015, 02:02:27 pm »
I finally have a reason to find my 89Ti again! This looks amazing. Keep it up.
I am Bach.

Offline catastropher

  • LV2 Member (Next: 40)
  • **
  • Posts: 30
  • Rating: +11/-0
    • View Profile
Update and Animated Walkthrough
« Reply #4 on: March 16, 2015, 10:26:01 pm »
@pimathbrainiac, thanks! :D I really appreciate the support!

So, over the past day I did a number of things:
  • Fixed the x4 overdraw problem
  • Added backface culling
  • Removed redundant edges so walls look more realistic and feel more solid
  • Expanded the level
  • Reduced the stack usage in my recursive render_cube() function, which was causing a stack overflow
With these improvements, the engine runs at 3-4 times the previous framerate! There are still several optimizations that I can do, however, so over the next few weeks I'll work on implementing them. Also, there are several bugs in the renderer, such as the one that can cause the screen to blank at certain locations in the map... I must look into this...  I will edit the first post soon with the new binaries as soon as I fix a few more bugs.

Anyway, here is an animated screenshot of me "flying" through the test level. Note that the fps on the emulator is ~2 fps slower than on the real calc for some reason.

Spoiler For X3D walkthrough:


Offline TIfanx1999

  • ಠ_ಠ ( ͡° ͜ʖ ͡°)
  • CoT Emeritus
  • LV13 Extreme Addict (Next: 9001)
  • *
  • Posts: 6173
  • Rating: +191/-9
    • View Profile
Re: Descent 68k/X3D
« Reply #5 on: March 17, 2015, 11:04:55 am »
This looks quite nice! I'll have to put it on my calc and give it a try. :)

Offline catastropher

  • LV2 Member (Next: 40)
  • **
  • Posts: 30
  • Rating: +11/-0
    • View Profile
Re: Descent 68k/X3D
« Reply #6 on: April 05, 2015, 11:10:39 pm »
Thanks @Art_of_camelot! So, I wanted to give a status update. Here are the features I have worked on implementing since my last post:
  • Several optimizations and bugfixes
  • The ability to import a Descent I level (registered or shareware)
  • Gravity
  • Better collision detection and ramps!
While the engine *can* import an official Descent level, it unfortunately has numerous rendering problems and renders at <1 FPS :( So, in the meantime, I'm using the official level editors as an editor to create simple test levels. Here is a screenshot of one in the editor:
Spoiler For Spoiler:

Here's an animated screenshot of the level in action (though it still has some rendering glitches):
Spoiler For Spoiler:

I present the project on Wednesday, and after I clean up the code a bit, I'll be publicly releasing it. I will probably be rewriting the engine as a long-term goal to have a better level structure and overall design. In the meantime, however, I want to implement the following features:
  • Vector graphics (i.e. "texture"/wall decorations made of lines/simple filled polygons)
  • Switches
  • Doors
  • Elevators
  • A simple weapon
  • Facing sprites
You may be wondering if this will still be a game of Descent. The answer is, I'm not sure. Certainly it will turn into a 3D game engine (much like FAT but with true 3D), but I'm not sure if the calculator will be able to handle a full level. I've thought of a way to simplify the geometry into convex regions (instead of just cubes), but this will require an engine rewrite. We will see though :)

As always, thank you for your continued interest in X3D! I look forward to posting my progress in the future!

Offline Matrefeytontias

  • Axe roxxor (kinda)
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1982
  • Rating: +310/-12
  • Axe roxxor
    • View Profile
    • RMV Pixel Engineers
Re: Descent 68k/X3D
« Reply #7 on: April 06, 2015, 04:10:42 am »
Wow that looks very cool !

Textures are always a big deal with calculator 3D engines, because they require a loooot of processing power. As far as I know, the only engine that's fast enough to provide textured polygons is nGL on the TI-Nspire because this calc has a lot of processing power actually.

Offline ben_g

  • Hey cool I can set a custom title now :)
  • LV9 Veteran (Next: 1337)
  • *********
  • Posts: 1002
  • Rating: +125/-4
  • Asm noob
    • View Profile
    • Our programmer's team: GameCommandoSquad
Re: Descent 68k/X3D
« Reply #8 on: April 06, 2015, 07:26:16 am »
Textures are always a big deal with calculator 3D engines, because they require a loooot of processing power. As far as I know, the only engine that's fast enough to provide textured polygons is nGL on the TI-Nspire because this calc has a lot of processing power actually.
* Ben_g  points to :P

If you have problems handling bigger levels, then it's ofthen best to divide them into a few sections. Then for every one of those sections, you have a small list which indicates which other sections are visible from that section. Then you only render the section you're in and the sections visible from there.
You'll have to put a bit more work in your levels to do this, but it makes it possible to have much bigger levels with minor overhead.
I've used this trick a few times in some unreleased test projects of mine, to render environements that are too big for the 84+ to render, like entire race tracks.
My projects
 - The Lost Survivors (Unreal Engine) ACTIVE [GameCommandoSquad main project]
 - Oxo, with single-calc multiplayer and AI (axe) RELEASED (screenshot) (topic)
 - An android version of oxo (java)  ACTIVE
 - A 3D collision detection library (axe) RELEASED! (topic)(screenshot)(more recent screenshot)(screenshot of it being used in a tilemapper)
Spoiler For inactive:
- A first person shooter with a polygon-based 3d engine. (z80, will probably be recoded in axe using GLib) ON HOLD (screenshot)
 - A java MORPG. (pc) DEEP COMA(read more)(screenshot)
 - a minecraft game in axe DEAD (source code available)
 - a 3D racing game (axe) ON HOLD (outdated screenshot of asm version)

This signature was last updated on 20/04/2015 and may be outdated

Offline catastropher

  • LV2 Member (Next: 40)
  • **
  • Posts: 30
  • Rating: +11/-0
    • View Profile
Re: Descent 68k/X3D
« Reply #9 on: April 06, 2015, 08:48:03 am »
Hey guys, thanks for the input!

Textures are always a big deal with calculator 3D engines, because they require a loooot of processing power. As far as I know, the only engine that's fast enough to provide textured polygons is nGL on the TI-Nspire because this calc has a lot of processing power actually.

Bitmap textures are indeed very expensive to draw; even if I could get it to work, the engine already requires significant CPU power for the other stages of the rendering pipelines (rotating, projecting, 2D clipping, 3D clipping, etc). However, my engine is geared towards drawing/clipping lines and polygons, so the "textures" are not bitmaps, but a series of 3D lines and polygons that are "attached" to the wall (i.e. vector graphics). Suppose that I wanted to draw "Hello" on a wall. Instead of drawing the pixels that make up the 'H', I could instead store the 3D lines that make it. Then, it's easy and fast to draw because it's just a bunch of lines instead of having to do perspective-correct texture mapping. While this does limit the type of "textures" you can create, I think it's better than having all blank walls.

If you have problems handling bigger levels, then it's ofthen best to divide them into a few sections. Then for every one of those sections, you have a small list which indicates which other sections are visible from that section. Then you only render the section you're in and the sections visible from there.
You'll have to put a bit more work in your levels to do this, but it makes it possible to have much bigger levels with minor overhead.
I've used this trick a few times in some unreleased test projects of mine, to render environements that are too big for the 84+ to render, like entire race tracks.

In a way, this what the engine currently does. Since it's a portal renderer, if the portal isn't visible, whatever's on the other side isn't either. The levels themselves are made up of interconnected cubes; when two cubes are connected, the face that they share is the portal. It works by starting at the cube you're currently in and recursively rendering neighboring cubes until it hits the recursion limit or there's nothing left to render. However, this means that you still have to consider each potentially visible portal and send it through the polygon clipper, even if it turns out it isn't visible (which sadly is an n^2 algorithm :(). I do like this idea though because it may really cut down on the number of cubes the renderer has to consider. I wonder if there's a way to efficiently programmatically determine potential visible sets...

Offline ben_g

  • Hey cool I can set a custom title now :)
  • LV9 Veteran (Next: 1337)
  • *********
  • Posts: 1002
  • Rating: +125/-4
  • Asm noob
    • View Profile
    • Our programmer's team: GameCommandoSquad
Re: Descent 68k/X3D
« Reply #10 on: April 06, 2015, 04:53:06 pm »

Bitmap textures are indeed very expensive to draw; even if I could get it to work, the engine already requires significant CPU power for the other stages of the rendering pipelines (rotating, projecting, 2D clipping, 3D clipping, etc). However, my engine is geared towards drawing/clipping lines and polygons, so the "textures" are not bitmaps, but a series of 3D lines and polygons that are "attached" to the wall (i.e. vector graphics). Suppose that I wanted to draw "Hello" on a wall. Instead of drawing the pixels that make up the 'H', I could instead store the 3D lines that make it. Then, it's easy and fast to draw because it's just a bunch of lines instead of having to do perspective-correct texture mapping. While this does limit the type of "textures" you can create, I think it's better than having all blank walls.
For a calculator, you shouldn't have to do perspective corrected texture mapping. You get almost as good results from affine texture mapping if the textures aren't stretched too much. And calculation-wise, textured triangles were about 2-3 times as heavy as the solid ones (Though I have to admit: both the solid and the textured triangle drawing routines were terribly optimized). So, depending on the complexity of the textures you use and how efficiently your engine does the 3D to 2D conversion, a bitmap could sometimes be faster.
My projects
 - The Lost Survivors (Unreal Engine) ACTIVE [GameCommandoSquad main project]
 - Oxo, with single-calc multiplayer and AI (axe) RELEASED (screenshot) (topic)
 - An android version of oxo (java)  ACTIVE
 - A 3D collision detection library (axe) RELEASED! (topic)(screenshot)(more recent screenshot)(screenshot of it being used in a tilemapper)
Spoiler For inactive:
- A first person shooter with a polygon-based 3d engine. (z80, will probably be recoded in axe using GLib) ON HOLD (screenshot)
 - A java MORPG. (pc) DEEP COMA(read more)(screenshot)
 - a minecraft game in axe DEAD (source code available)
 - a 3D racing game (axe) ON HOLD (outdated screenshot of asm version)

This signature was last updated on 20/04/2015 and may be outdated

Offline Vogtinator

  • LV9 Veteran (Next: 1337)
  • *********
  • Posts: 1193
  • Rating: +108/-5
  • Instruction counter
    • View Profile
Re: Descent 68k/X3D
« Reply #11 on: April 06, 2015, 05:30:35 pm »
Quote
For a calculator, you shouldn't have to do perspective corrected texture mapping. You get almost as good results from affine texture mapping if the textures aren't stretched too much.
That's correct, nGL doesn't use the Z coordinate for texture interpolation. It simply maps the triangle edges to screen edges and interpolates linearly.
That's still two divisions per scanline, but the memory speed is the limitation here. The CPU on the nspire is fast enough to do calculations, but the RAM is really slow.

Quote
Suppose that I wanted to draw "Hello" on a wall. Instead of drawing the pixels that make up the 'H', I could instead store the 3D lines that make it.
How well does that scale? I assume you're not using a z-buffer, but sort the faces before drawing. (Surprisingly, a z-buffer is faster than sorting faces on the nspire, even for moderately low-poly scenes)

Offline catastropher

  • LV2 Member (Next: 40)
  • **
  • Posts: 30
  • Rating: +11/-0
    • View Profile
Re: Descent 68k/X3D
« Reply #12 on: April 06, 2015, 05:57:40 pm »
Quote
Suppose that I wanted to draw "Hello" on a wall. Instead of drawing the pixels that make up the 'H', I could instead store the 3D lines that make it.
How well does that scale? I assume you're not using a z-buffer, but sort the faces before drawing. (Surprisingly, a z-buffer is faster than sorting faces on the nspire, even for moderately low-poly scenes)
Interestingly enough, X3D doesn't draw any triangles whatsoever. Instead, it exploits a few properties of the level design. First, all of the cubes can be rotated/stretched/skewed, but they have to remain convex. This means that for a given cube, (with backface culling) we can draw the sides in any order without a Z-buffer or depth-sort. Second, a cube can be connected to another cube by having them share a face. I then just set the clipping region to be the shared face before drawing the child and clip the lines of the child's polygons against it. Since the calculator renders in monochrome and there is zero overdraw because of the clipping region, there is actually no need to clear any triangles; I just clear the screen before rendering and draw the outlines of the polygons.

For a calculator, you shouldn't have to do perspective corrected texture mapping. You get almost as good results from affine texture mapping if the textures aren't stretched too much. And calculation-wise, textured triangles were about 2-3 times as heavy as the solid ones (Though I have to admit: both the solid and the textured triangle drawing routines were terribly optimized). So, depending on the complexity of the textures you use and how efficiently your engine does the 3D to 2D conversion, a bitmap could sometimes be faster.
Since I'm not clearing any triangles, if I want to draw the vector wall graphics, all I have to do is throw them at the polygon clipper. If they want a filled white polygon that's outlined, the wall is already white so we only have to draw the outline. If, on the other hand, they want a black filled polygon, we just once again clip it and draw some black-filled triangles. There's no need to even draw the outline in that case! Perhaps I will upload an image to clarify what I mean by this.

Offline catastropher

  • LV2 Member (Next: 40)
  • **
  • Posts: 30
  • Rating: +11/-0
    • View Profile
Re: Descent 68k/X3D
« Reply #13 on: April 09, 2015, 07:18:21 am »
So I'm getting ready for the presentation today and I expanded the level by adding a light bridge and a holo-panel switch (with some dramatic effects) :D

Spoiler For X3D Light Bridge:


Offline Sorunome

  • Fox Fox Fox Fox Fox Fox Fox!
  • Support Staff
  • LV13 Extreme Addict (Next: 9001)
  • *************
  • Posts: 7920
  • Rating: +374/-13
  • Derpy Hooves
    • View Profile
    • My website! (You might lose the game)
Re: Descent 68k/X3D
« Reply #14 on: April 09, 2015, 07:22:56 am »
I just love it! :D

THE GAME
Also, check out my website
If OmnomIRC is screwed up, blame me!
Click here to give me an internet!