When I started my current freelance project, I knew close to nothing about 3D animation in the web. Initially, I figured that I could learn Three.js and complete the freelance project. But the catch was I didn't know the depth of things in the 3D world. In essence, I was way over my head.

— Andrew Gremlich (@agremlich.bsky.social) April 12, 2025 at 6:22 PM

In this Bluesky post, I mistakenly thought that AI could finish a simple 3D slicer for me, but I found out that if I didn’t know the intended solution and understand the technology then I couldn’t finish the problem. I intend to dive a little bit more into the essential need of problem solvings skills even with AI assistants.

Stopping AI Use

When I was getting no where with using AI in my freelance project, I recognized that I had to stop and think about the problem. If I were to move forward with the project, I had to understand the problem that needed to be solved. If I couldn’t sufficiently explain the problem to AI, then how could I expect to use it?

First problem, I didn’t really know what a traditional slicer did. My first assumption was to compile all the STL points in the project into GCode toolpaths, but intuition told me that stuffing STL data points into a GCode file could get unwiedly and problematic. The outputted file was way to big for a 3D printer and sub-millimeter toolpath changes seemed just dumb. As well, I couldn’t reliably predict if the STL data points would be in the order that I needed. I needed to have properly customized solution.

I searched around the internet for open sourced slicing projects. I found a couple, and I started reading the code to see what I could be missing. I found that these projects were using the Raycaster class from Three.js, and that class had an intersectsObject method. A ray caster is just a ray in 3D space and it uses Linear Algebra to calculate an intersection. As I gathered more information from these projects, this seemed like the right direction to go with my project.

Getting an Idea for a Solution

If I were to use Raycaster and intersectsObject, what would that look like? The Raycaster can have an origin in the center of the STL model, and the direction would rotate in a circle around the model. So then I can increase the definition of the model by how many slices of a circle I have. But wait! That would only be a level slice, and the requirements needed it to be a vase slice meaning progressively increase the height of the toolpaths. I’ll increase the height of the origin with every rotation, and I’ll calculate the height change by dividing the 3D printer’s nozzle with by the slices of the circle. Yeah this is becoming a better solution!

Oh no, there’s some trigonometry here and I haven’t done trig in 15 years. How am I going to figure that out? Well, it turned out AI helped very well with that point, but this lesson is making me think I should go back into math. Refamiliarizing myself with math could help me with problem solving some more. But that’s just a side note.

So, I built a raycaster workshop to validate the things that I would need. The workshop had a raycaster origin in the center of a simple model with the direction going in some predetermined way. Buttons would manipulate the origin and direction of the raycaster through trigonometry, and the workshop would find the intersection in the model and put a dot at the intersection. Knowing what I needed, I starting coding it out in my freelance project, and Github Copilot helped me out along the way.

Side note, I also learned about “Bounding Volume Hierarchy” but I’ll talk about that some other time.

A wizard draws math equations on a whiteboard.

Let’s stop and break the problem down in order to understand what the solution should be.

How Does This Work?

While breaking down a problem is crucial, understanding how a solution works is equally important. Perhaps a bug appears and I’m back at square one with needing to break down a problem. I found this post explaining Möller-Trumbore algorithm and how it revolutionized ray casting in the 3D industry for its speed. In 3D space, every model is made up of millions of tiny triangles, and a ray that is casted into these triangles can help determine the distance from the origin to the triangle and where the ray intersects the triangle.

I looked into Three.JS source code to see how Raycaster class worked, and, to my inexperienced surprise, I found Möller-Trumbore algorithm being implemented. I say inexperienced because if I was more experienced I bet I would have known that the developers behind Three.js would have used the algorithm.

My implementation of the Raycaster class essentially involved scanning through every triangle of a model to see if the raycaster intersected. Uh oh, this seemed inefficient. I put some STL models into my application, and I found that processing times would take longer than liked. This would have to be improved, but I’ll explain that with the “Bounding Volume Hierarchy” post coming up!

Conclusion

The fundamental problem solving skills are still important for software engineers even in the age of AI coding assistants. A software engineer ought to at least know how a problem should be solved in order to explain the solution to the AI. Tools are meant to help efficiency, but if AI is applied to literally everything then it follows the “all you have is a hammer, everything looks like a nail” metaphor. Sure, “hammering” everything in software engineering could still work, but things might not look pretty. Understanding how something works and knowing how to explain something to an AI will help a software engineer become more effective and efficient in his or her own career.

References

  1. Möller-Trumbore algorithm
  2. JS Workshop