Open Source 3D Arduboy project

(Blake) #1

I am working on a STL file driven 3D engine for use on the Arduboy.

No idea if this is of any use to anyone, but its there if interested. I have an academic goal in mind of creating a cloud debugging utility that runs on the AVR IoT WG(Atmega4808). I am using this project to vet that work. There is a lot of code related to the matrix multiply operation. This will be optimized, however I need a working unoptimized version for comparison. I want to research the improvements in the debbuger.

2 Likes
(Kevin) #2

This seems very esoteric but I am interested. Could we 3d print from an Arduboy? :smiley:

(Blake) #3

I was thinking someone could easily port this to an AVR based printer, creating a proper on device preview. I might gamify this a bit more to create something like a Daytona USA experience, but my research needs come first.

(Blake) #4

I ended up building out a full demo. Rush contains a large model with 354 polygons and while it isn’t a full on game I think it is enough for someone with more time, 3D interest, and more artistic skill to take a look. Models are imported from ASCII STL files so content creation is straightforward.

Rush does require a command line build. It uses the standard Arduboy2 and ArduinoCore-avr submodules in its git repo so the scary factor is somewhat reduced. If interested, let me know and I would be happy to help get everything started.

(Kevin) #5

Can you share the game hex or the github? Interested to see the performance!

(Blake) #6

Posted.

A to advance the screen, left right for vehicle selection, a to watch the vehicle crash.

Each vehicle from left to right has less polygons, so expect better performance. The smallest is the motorcycle at 144 polygons(triangles). To get a proper 24fps, I think you would need a model around 60 polygons. Are there any solid estimates of screen draw time?

(cyril guichard) #7

Tagging this post to follow development - I’m super busy this incoming week, but after that I could look at providing ultra-low-poly models.

(Blake) #8

I created a much simplified version devoid of the nest of prototyping code I created previously.
This version builds directly in the Arduino IDE as a standard sketch. It isn’t as optimized, but it is much easier to modify.

Includes a prebuilt .hex as well.

1 Like
(Pharap) #9

Ah, now I can actually make sense of it (mostly).


You might want to consider replacing memset.

struct param
{
    float value[BUFFER_SIZE] {};
    int8_t shape[2] { 3, 1 };
};

Before:

Sketch uses 15666 bytes (54%) of program storage space. Maximum is 28672 bytes.
Global variables use 1805 bytes (70%) of dynamic memory, leaving 755 bytes for local variables. Maximum is 2560 bytes.

After:

Sketch uses 15450 bytes (53%) of program storage space. Maximum is 28672 bytes.
Global variables use 1805 bytes (70%) of dynamic memory, leaving 755 bytes for local variables. Maximum is 2560 bytes.

Replacing memcpy might also have a size impact, but it depends on usage.


Also, worth pointing out:

float C[(int8_t)(A.shape[0]*B.shape[1])];

Standard C++ doesn’t allow variable length arrays,
that’s a compiler extension,
so be careful if you have any plans to port this code.

(Blake) #10

I made the memset changes at commit 4761e5dd1b432fb7d6329cdb15bb068e6562133c.
Thanks for the suggestion.

Yeah, I like writing code with variable length arrays. To me it is much cleaner and I have only ever experienced incompatibility on Windows. I’d prefer to leave that code in there for now, but I get that it lacks a level of purity.

1 Like
(Pharap) #11

It’s not just a ‘purity’ thing, there’s various other issues with them as well.


I didn’t really think about it earlier, but now I’m thinking about variable sized arrays, I just remembered that they’re going to have a size and performance penalty.

Using a variable size ends up making the code more expensive because the code has to:

  • Fetch shape[0]
  • Fetch shape[1]
  • Multiply them
  • Move the stack pointer by the result
  • Move the stack pointer back when the scope ends

Whereas with a fixed size it’s just

  • Move the stack pointer by a constant amount
  • Move the stack pointer back when the scope ends

As a test I had a go at replacing the variable length arrays in drawModel with some fixed size arrays: C[3], I[3] and L[4].

Before:

Sketch uses 15466 bytes (53%) of program storage space. Maximum is 28672 bytes.
Global variables use 1805 bytes (70%) of dynamic memory, leaving 755 bytes for local variables. Maximum is 2560 bytes.

After:

Sketch uses 15050 bytes (52%) of program storage space. Maximum is 28672 bytes.
Global variables use 1805 bytes (70%) of dynamic memory, leaving 755 bytes for local variables. Maximum is 2560 bytes.

I tested to be sure, and as far as I can tell the output is the same.

(Blake) #12

I am mostly testing using cpuLoad now, and by that metric it is a also a bit better. I’ll take whatever I can get for performance at this point, a21f67a900f2b683df6e43516f436a6efc56cff0.

1 Like
(Blake) #13

I ported the compressed model builder to javascript, added the source to the IDE project, and created a basic page to convert ASCII STL files in browser.

This is likely as far as I am going to take this project at the moment. If anyone wants to attempt a game with this code in the future, I’d be happy to assist.

http://starlo.org/blake/modelbuild/