Explore the time propagation of solutions to PDEs (partial differential equations) on surfaces in 3D space in this interactive sandbox!
This project was written using C++ and OpenGL.
The Finite Element Method was used to numerically solve these PDEs which requires using a lot of Linear Algebra in combination with some Multivariable Calculus.
Shubh
Check their projects out: Songbook, UIL Downloader, Maze Playground, Wavefunction Screensaver
Arjun
Check their project out: Monotony
Once you ship this you can't edit the description of the project, but you'll be able to add more devlogs and re-ship it as you add new features!
Alright, so I spent a lot of time writing a README.md, recording a demo video, and building and testing the project on Windows and macOS. I think I should be able to ship this project pretty soon!
Yeah, so I told myself I was going to write a README and record a demo video so I could get this project shipped today, but a little voice in my head told me to keep trying to get the Gray-Scott Reaction Diffusion model working (my first attempt failed last weekend). Surprisingly, I actually was able to figure it out, so now there's a cool, nonlinear pattern formation PDE in my program! Aside from that, I made some UI tweaks and added a pop up for when numerical instability occurs that resets the solver.
I added to the repository as a PDF the notes I took while learning finite element from online lectures on YouTube. I also wrote a cleaned up version of my derivations for the linear systems of each equation currently implemented in the program and added them to the repo as images.
Shorter devlog this time: Downgraded the project to OpenGL 3.3 Core, made a new icon, and replaced the old colormaps with some new ones.
I meant to split this into multiple devlogs but I forgot lol. I spent a lot of time revamping the GUI alongside ironing out bugs and adding error checking in some spots (like file loading).
I also decided not to write a GPU solver (definitely not because I am too lazy). This means that I can switch down to an older version of OpenGL that supports macOS since I no longer need compute shaders.
I spent way too long getting BVH (Bounding Volume Hierarchy) optimization to work so that mouse picking to draw on the mesh is now O(log n) instead of O(n). To speed up the solver even more, I am (hopefully) going to write a sparse matrix conjugate gradient solver with compute shaders to take advantage of the GPU for parallelism. Before that though, I need to clean up my code a bit as well as make an actual UI that isn't just buttons.
+added importing meshes through .obj so that you can solve PDEs on non-planar surfaces.
+added two new solvers: Wave Equation and Advection-Diffusion Equation.
+the surface is now a height map based on the value of the node at each vertex.
+the brush can now be dragged and time steps occur every frame.
Before I finalize this project and ship it, I still want to add BVH optimization for mouse picking, GPU solvers using compute shaders, and improve the UI.
It's been a while since I've worked on this project, but today I just did some refactoring including writing documentation to get reacquainted with the code base after a week long break.
I wrote this resource manager class (which right now is basically just a wrapper around std::unordered_map) which allows me to better manage things like shared shaders and meshes across the project.
It's been a few days since my last devlog since I've only been working a little less than an hour each day. However, I did get the CPU solver to work with the 2D Heat Equation with zeroed Dirichlet boundary conditions with the help of Eigen, a C++ Linear Algebra library.
Once a surface is created by triangulating a planar straight line graph (or, later on, importing a .obj file), the solver is initialized which sets up the stiffness and mass matrices using Eigen's sparse matrices (matrices where the entries are mostly zero).
From there, time stepping is performed using an implicit Euler scheme and the Conjugate Gradient method provided by Eigen, which works very efficiently with sparse matrices. Right now the time stepping is triggered by a button in the GUI but I plan to have it constantly run every frame so the user can see the propagation of the solution more smoothly.
I learned most of this from watching Professor Qiqi Wang's lectures on Numerical Methods which I found on YouTube (https://www.youtube.com/playlist?list=PLcqHTXprNMIOEwNpmNo7HWx68FzBTxTh3). I took a bunch of notes on paper, but I plan to digitize them so I can include them with the repository as a large part of the work on this project was understanding the fundamental procedures for FEM.
Surprisingly I finished quite a lot in only about 2.5 hours.
- I added the ability to designate closed regions as holes so that they do not get triangulated. You can see this in action at the beginning of the video.
- After that, I added these little sphere meshes that are rendered in the positions of the nodes and take on the color based off of a color map and the node's value (in this case it is Viridis from matplotlib which I copied from here https://www.shadertoy.com/view/Nd3fR2). I also plan to have an option where the height of the vertex changes depending on its value.
- Added a colored mesh where the colors are determined by interpolating the colors of its 3 vertices across each triangle's surface.
- Added a brush that sets the value of all the nodes of a triangle via mouse picking.
The next step after this is probably going to be implementing the FEM solver on the CPU for the 2D Heat Equation. Be warned though, the solver is going to be excruciatingly slow! I do plan to write a GPU accelerated solver later on once I get the CPU version working.
I added PSLG triangulation so now we are one step closer to the FEM solver (at least for planar surfaces). On top of that, I added some more GUI elements, namely a pop up window to catch invalid use of the triangulation button and a small window that appears in the top left of the viewport that displays controls for the current mode.
I added the ability to draw PSLG's (Planar Straight Line Graphs) on the XZ plane using the mouse.
To extend this, I plan to add a feature that allows users to import an image into the world as a 2D quad to act as a stencil to trace the PSLG over as well as have an option to export and import saved PSLG's to and from a file for convenience.
The next step from here is to triangulate this into a mesh suited for FEA using the triangle library I added earlier.
Added a little sidebar for the GUI that can be toggled on and off. This is where are all the sliders and other menu items will reside.
I spent some time refactoring the code to be more modular so I can avoid headaches later down the line lol
I set up an OpenGL C++ repository along with some other utility libraries such as triangle (2D triangulation library) and tinyobjloader.
After that, I started 3D rendering with an orbital camera that can rotate around a point, pan to move said point, and zoom in and out from the point. Also, you can switch between a perspective and orthographic projection (which will be useful when switching between the 3D and 2D mode).
Finally, I made it so that the orbit point and the grid (y=0) are drawn which creates a better sense of space in the scene.