A Breath Module threejs project example
I made a javaScript module that can be used as a core tool in the process of making a number of video projects that can be used as tools for controlled breathing exercises. The core idea of these kinds of videos is to have a number of objects update in such a way that they are in sycn with a rate at which people watching the video breath. So there is a lot of little details that come up when making a javaScript module to update things such as how many breaths per minute, how many minutes, and also other details about each breath cycle. Details for each breath cycle are things like what is the ratio of time for each opening reset, breath in, high rest, and breath out part. There are also a lot of things that come to mind when it comes to having an expression for the alpha values that will be used to position objects along curves, and also update just about everything else.
The breath module example and what to know first
This is a blog post on a javaScript IIFE form module threejs project example, and several demos of the module, that work on top of threejs in a front end javaScript environment. It should go without saying but I have to say it in each of these posts, this is not a post for people that are new to threejs let alone javaScript in general. I assume that you have at least a fair amount of experience with the skills that are required before hand to get something of values from reading this. Still in any case I do use these opening sections to wrote about a few things that you might want to read up more on regardless of experience.
IIFE and JSM
As of this writing I still follow and old IIFE pattern for making javaScript modules which is in line with the use of three.min.js over that of three.module.js. However at some point in the not to distance future I will have to start wiring new modules and updating old ones in the JSM format.
Source code is up on Github
I have the current sould code for this module and the demos up on my test threejs repository on Github. This is also where I place the source code examples that show up in all my other blog posts on threejs as well.
Version Numbers matter
When I first wrote this blog post and made the first version of this module I was using r146 of threejs and thus follow that style rules I set for that revision. I am also at the time of this writing at least sticking to my tired yet true IIFE pattern for javaScript modules. The plan with new posts and editing older posts is to stick with this well into this coming year, but still the days with this kind of style are very much coming to an end. The three.min.js files that I have been using are very much on the chopping block it would seem, so at some point I am going to need to start including JSM versions of my module for people that want to use bleeding edge revisions of threejs.
In any case always be mindful of what revision of threejs that you are using when trying to get code examples such as the ones I am writing about here to work on your end. Code breaking changes are made to threejs all the time so it often is best to stick with the revisions that I am using with these examples. Also I have found that it is a good idea to be aware of what kind of GPU you are using on your system and what the support is for OpenGL and therefor WebGl features. I like working on Raspberry PI OS and thus also have to deal with the limitations of the VideoCore VI GPU of the Raspberry PI 4. In r150 of the library the WebGLRenderer has totally crashed and burned which cased me to start plaing future code style rules with r149. Simply put in general version numbers very much matter with this stuff, and not just with threejs alone.
1 - The First version of the breath module, and some demos
There is then covering the state of the breath module itself, and then also getting into a few demos as a way to test drive what I have thus far. With that said there are two general public methods of interest one of which is used to create an instance of THREE.Group, with a whole bunch of useful data attached to the user data object of this group which is very much there for these kinds of projects. The other public method if interest is used to update the state of these values.
This far the module seems to work okay with what I have in mid thus far, and as of now the current panes for future revisions have to do with reducing complexity actually rather than adding features.
1.a - Breath.js R0
The current state of the source code of the module is broken down into three general parts thus far. One part is for defaults and constant values for versions things over the body of the source code. ANother part has to do with private helper functions that are used as tools for the final part which is the pubic API of the module.
|
|
1.1 - Using the default options
I will want to start out with a demo of the module that is a kind of hello world type getting started type demo. Nothing fancy just creating an instance of the group that is returned when calling the breath modules create public method. Also with that said I can make sure that i get an expected result when calling the create method with no options at all that will of course result in a breath module with everything set to the hard coded default settings for thing.
|
|
1.2 - Custom options for curve and mesh updates
So it looks like this are working just fine with the default settings so now it is time to have a demo with some custom options for update the group of mesh objects.
|
|
1.3 - The hooks option
I also have a hooks feature that is a way to define custom logic for each part of a breath cycle.
|
|
Conclusion
So far so good with this project, and I am sure that i will be making at least a few video projects using this module. In time I am sure I will have a better idea of what needs to change with respect to future revisions of this module. Thus far I am thing that much of that might have to do with removing features rather than adding them actually. The general idea that i have now is that the core of the module itself should just be used to create and update alpha values that I then use to update everything else with the children of the group, but also objects the exist outside of the group as well. I still think that the create method should return an object3d class based object though, so I am thinking that I might want to have some kind of plugin system with maybe a very basic built in functionality that can be replaced by way of one or more options plugins.