@UnsignedArduino's updates

Let’s see how long I’ll keep this up. (dev log to force myself to post updates, works in progress, etc.)

14 Likes

woah, I actually posted something. also damn this post took forever to write.

This is dev log #1.


A First Look at C3D

C3D (Cyrus’ 3D), is a general-purpose three.js-flavored 3D engine for MakeCode Arcade: a pleasant object API for users, with flat arrays and tight loops underneath for a fast renderer. It’s
designed around the 16-color 160x120 simulator; running on hardware is not a goal.

A GIF of three identical cubes with different face colors rotating at different rates Suzanne the Blender Monkey rotating CCW on the Y axis
Utah Teapot rotating CCW on the Y axis Stanford Bunny rotating CCW on the Y axis

And the name? Originally, I was thinking of U3D - UnsignedArduino’s 3D - but @Unique already has U3D - looks like there are only 24 letters left for MakeCode Arcade 3D engines!

Demos

Controls for the demos above are WASD for camera translation (P1 controls), Q/E or space/enter to raise up and down, IJKL for camera rotation (P2 controls).

Mesh imports are from a preliminary script one-shotted by Claude. I plan on releasing an actual tool to help import these models and also support a basic fromOBJ method directly within C3D.

Preliminary Benchmarks

Preliminary performance numbers are tested on my personal laptop: Google Chrome 154 incognito with JavaScript V8 15.4.80.20, Windows 11 Version 25H2 (Build 26200.9457), ASUS Vivobook S 16 (Ryzen AI 9 HX 370, 32 GB unified DDR5, 1 TB NVMe) running off power (not battery). I’d love to hear what kind of performance you get with your device! (open the inspect console at the default camera angle - I’ll have a more rigorous benchmark later)

Suzanne the Blender Monkey (total 555 vertices, 967 triangles)

l>tFrame: 1.101     (total frame time - all times in milliseconds)
tModelCollect: 0    (model collection in scene time)
tSetupAndMats: 0    (setup and material fetch time)
tMVPs: 0            (MVP multiply out time)
tVertexTrans: 0.199 (vertex transformation time)
tTriClip: 0         (triangle clip time)
tProj: 0.101        (projection time)
tRaster: 0.399      (triangle rasterization time)
pxTest: 5064        (pixels tested)
pxWrite: 4288       (pixels written to the screen)
tris: 614 / 967     (rendered / total triangles)
Utah Teapot (total 7421 vertices, 13966 triangles)

l>tFrame: 4.4
tModelCollect: 0
tSetupAndMats: 0
tMVPs: 0
tVertexTrans: 0.6
tTriClip: 0.7
tProj: 0.4
tRaster: 2.6
pxTest: 7368
pxWrite: 4231
tris: 7180 / 13966
Stanford Bunny (total 34834 vertices, 69451 triangles)

l>tFrame: 26.4
tModelCollect: 0
tSetupAndMats: 0
tMVPs: 0
tVertexTrans: 3.6
tTriClip: 2.9
tProj: 2.1
tRaster: 17.4
pxTest: 3632
pxWrite: 3558
tris: 28775 / 69451

Numbers from Claude:

Model Rendered tris/s Submitted tris/s Tested px/s Written px/s Pixels per rendered triangle
Suzanne 558 k 878 k 12.7 M 10.7 M 8.2
Utah Teapot 1.63 M 3.17 M 2.83 M 1.63 M 1.0
Stanford Bunny 1.09 M 2.63 M 0.21 M 0.20 M 0.13

Submitted is all triangles even before culling. Tested is a pixel from a triangle, written is if a pixel was closer on the screen (the z-buffer) You can see by the low pixels/rendered triangle that most triangles won’t be rendered, and these numbers mostly measure triangle setup. Suzanne’s numbers are close to browser timing measurement, so again, treat these are preliminary with a big caveat - these are stress testing many small triangles!

What’s Built

This extension is not ready for use in the sense that I’m still working on it - there isn’t even a version created in GitHub Releases! (Of course, you can import the extension, but as there isn’t a version, there’s no semver for me to follow, so breaking changes can happen at any time!) But what’s available includes:

  • Fast math objects including Vec3, Quat (for rotations), and Mat4 that include chainable methods.
  • A scene graph composed of Object3Ds. All have plain position, rotation, and scale vectors you modify intuitively.
  • PerspectiveCamera and OrthographicCamera.
  • Geometry and materials so far with Mesh and FaceColorMaterial.
  • The renderer core without lighting or shadows. It does transforms, near/far/side clipping, per-model frustum culling, back/front-face culling, and a z-buffer. No painter’s algorithm - we do our own span loop!

Developing Locally with mkc and JetBrains WebStorm, or Any Other IDE, Potentially Alongside AI Agents

Originally, I started this project within the regular MakeCode Arcade editor we all know and love dearly, but realizing the scope of this project, I decided to explore other methods to use more “full-featured” IDEs. Additionally, AI agents seem to be an ever-more-important thing to utilize, and so of course I wanted to also dip my toes into it, to see whether Claude in Claude Code could autonomously develop features, fix bugs, or create tests.

Of course, there is the great Microsoft MakeCode Arcade extension for Visual Studio Code, which even works on the web! But personally, my favorite children will be the IDEs by JetBrains (not sponsored by JetBrains; but they now have a lot of IDEs free for non-commercial use, or if you are a high school or university student, you may be able to use the GitHub Student Developer Pack!) with their Classic UI plugin. I’m also definitely way too used to their autocomplete engine, so it looks like after I graduate I’ll be shelling out the money for them :laughing:

Of course, you can’t just use the MakeCode Arcade VS Code extension inside WebStorm (another project for another day? :eyes:), but for extension development, you don’t even need all of the features in the VS Code extension that are essential to regular game development, such as editing images or songs. So, you can just run the mkc CLI tool locally! My experience with it has been great so far. If you want to consider making a complex MakeCode Arcade extension with another editor, I’d suggest this workflow, which is what I’m using for C3D:

Developing MakeCode Arcade extensions inside WebStorm or other non-VS-Code-related IDEs

  1. Have the mkc CLI tool installed (npm install -g makecode).
  2. Use https://arcade.makecode.com to create your project and push to GitHub. Yes, mkc can init a blank project locally (see the GitHub link above for docs), but it doesn’t seem to come with all the files that a normal MakeCode Arcade project comes with. And you’ll easily have a GitHub repo to store your code!
  3. git clone the repo and open it in WebStorm (or your favorite IDE)
  4. Run mkc install at the root of your MakeCode Arcade project so that WebStorm and the TypeScript engine can provide you with autocomplete and understand the structure of your code.
  5. Run mkc serve and open the localhost link to see the simulator run main.ts or test.ts. Any errors in the build process (e.g., undefined variable) will show up in this terminal with line numbers.
  6. Start developing - create and edit files normally and update pxt.json’s files list to ensure your code file actually gets included. Saving your files will prompt a rebuild and reload the simulator in the browser window. Don’t forget to commit and push your code!

And to continue development another day, just open back up the project in WebStorm, run mkc serve, and continue coding! I particularly enjoy this workflow, and it works for me because C3D doesn’t require me to edit images, tilemaps, etc., so the lack of those features without a suitable IDE extension/plugin means it doesn’t matter.

AI Agents Using the Simulator

If you want Claude Code or any other AI agents to try to write code, fix bugs, or look at the simulator, you can ask your favorite AI agent to use a browser MCP server, like the chrome-devtools MCP server, to open 127.0.0.1:7001 and read console.log outputs with the console tools or take a screenshot to confirm static visual output. For example, this is an excerpt of what’s in my CLAUDE.md for C3D: (ignore the \ below; they were messing up the code block formatting)

## Commands

This extension targets the simulator only (not hardware/micros). Use the `mkc` CLI
(`npm i -g makecode`), not `pxt`:

\```bash
mkc serve   # builds and serves the sim at 127.0.0.1:7001 — typically already running
mkc build -j   # run this specifically to check that a build succeeds
\```

`mkc serve` is normally already running in a terminal; saving a file triggers its own build and
reload, so `mkc build -j` is only needed when an explicit build check is wanted (e.g. before wrapping
up a change) rather than for routine edits.

To view output: make sure `mkc serve` is running, open `127.0.0.1:7001` with the chrome-devtools MCP,
read `console.log` output via the console tools, and take a screenshot to confirm visual output.

`test.ts` is where local-only test/benchmark code goes — per `pxt.json`'s `testFiles`, it never ships
with the extension. `tsconfig.json` targets ES5 with `noImplicitAny` on but
`strictNullChecks`/`strictPropertyInitialization` off; output goes to `built/` (gitignored except
what's checked in).

It’s instructed to also write any scratch code in main.ts or test.ts to test out changes or benchmark performance, typically through a lot of console.logs, as that’s the primary method it can easily get output from the simulator.

What’s Next

I plan for the next posts to be either progress on MakeCode-Arcade-to-App’s rewrite, detailed benchmarks on C3D’s performance, a writeup on simulator performance notes Claude found, or a writeup on one of the next features I plan to build:

  • Textures
  • Lighting and shadows
  • Model import tools

There are definitely more planned in store, though!

Of course, you can see the extension’s progress on GitHub:

Follow this thread to stay updated with the development of C3D. :grin:

AI Usage

AI, as referenced, refers to LLM-based technologies such as Claude and ChatGPT, matching the colloquial usage nowadays.

Currently, as a Computer Engineering undergraduate student, theoretically I should know both hardware and software. But of course, I’m just a wee little student still learning, so I’ve been collaborating and learning extensively from Claude (this post is not sponsored by Anthropic lol), both on claude.ai and Claude Code, as I’m building this project.

AI (mostly Claude) usage in this project includes:

  • Drafting and reviewing API design specs and decisions.
  • AI implementing code for boring or “less important” parts.
  • Spelling out the structure and providing hints as I manually code the critical parts of this extension, including the renderer.
  • Reviewing code.
  • Researching and testing code, especially to optimize performance in the simulator.

I’d say the work between me and AI is approximately 50/50. Of course, we could go on all day talking about the ethics and usage of AI in not just coding but in our work and life in general (and I do have my own opinions), but this post does not intend to start a battle between differing AI viewpoints. Of course, small comments on AI usage is acceptable, but I implore you to not start heated conversations on AI and waste moderator effort.

I do believe that it’s important to let you guys know that I have used and will continue to use AI to help me not just deliver this project in a reasonable timeframe but also learn 3D graphics programming and use AI effectively. And so, this is why I’ve included an AI usage section.

12 Likes

Bro just casually popping out of nowhere and posting like a 1000 word essay about his 3D engine that runs INSANLEY SMOOTHLEY AND QUICKLY LIKE WHAT. I wish I had this much aura :pensive_face:

All jokes aside, this is crazy! By lighting do you mean changing the color of a shapes face based on how far away it is? Also how do you plan to create worlds with this, would you have to code every single element of your scene or use some other cursed techniques.

1 Like

HOLY YAPYAP I DONT CARE /j also post these weekly and you get snake bombed by everyone if you don’t

4 Likes

Future plans include fog (fade to black or white or different color), but the lighting I’m primarily thinking about is the directional, spot, and point lights, alongside shadows that models cast. No RGB obviously so pixels only get darker from unlit (what you see)

There are plans to have easy builders like box, plane, sphere, cylinder, etc., and you can set a single color, per-face color, or texture to add to it. Maybe heightmap from image. Blocks API to easily do this is a little more difficult but I plan on having blocks eventually. I also plan on having a tool that converts OBJs and other mesh files to the number arrays or some other import format, so you can design in Blender or download models from the internet.

haha I’ll try, but again, being an engineering student, co-op applications, and marching band mean time and/or sleep is scarce :sweat_smile:.

2 Likes