The Math Utils in threejs
Baked into threejs there are a number of Math utilities that can be used to help with various tasks such as clamping values for one example. Other things that can be done with the various methods include things such as converting a degree value to a radian value, or getting pseudo random values by way of the seeded random method.
However there is not just thinking in terms of what there is to work with, but also what is missing when it comes to a collection of methods such as this. With that said I think I should also write about one or more additional things that are not in this math utils object, but should maybe be there. Even though there are some usual suspect type methods to work with here I can not say that this is a replacement for some kind of additional utility library outside of threejs. As I still find myself writing my own code for various things in order to fill in the gap sort of speak.
Speaking of filling in the gap when it comes to making my own module for the kinds of methods in the math utils object, sense I am always working on top of threejs I can just simply wrap many of the methods in the Math utils object. For one example of what I mean by this when it comes to the subject of wrapping a value, maybe I need to still need to make my own own method for that, but when it comes to having a clamp method I can have that just call the clamp method in the Math Utils object.
The math utils method and what to know first
There is a Clamp method but no Wrap method in Math utils
Many libraries will have a clamp method that will clamp a value to the range of a given max and min value, and threejs is no exception with this as there is very much a clamp method in the math utils object. However there is not just clamping values but also wrapping values as well. That is that on top of having a method that will clamp a value between a min and max value in that it will just not let the value go lower or higher there would also be a wrap method that will wrap a value that goes beyond max back to the min value and vice versa. it would seem that there is no wrap method in the math utils object, thus I have to get this method by using or making something outside of the library. There is however an Euclidean Modulo method that is kind of similar to what I would expect, it is just that I also would like to have something that works a little differently when it comes to negative numbers.
I have wrote a blog post on this subject of wrapping Vectors and primitives in which I was able to find a decent wrap method, and I also made one of my threejs project examples that is a wrap module in which I am building on top of this kind of thing. Also with some of these examples I am using a wrap method that I came up with when working on those source code examples.
Source code example in this post are on Github
The source code examples that I am writing about in this post are up on Github. This is also where I am parking the source code examples for all my other various posts on threejs.
Version Numbers matter
When I first wrote this post I was using r135, and the last time I came around to do some editing of this post I made sure all the examples where still working okay with r140. Always check what version you are using when reproducing things on you end, as code breaking changes are made to threejs often.
1 - Basic example of threejs math utilities using degree to radian method when setting the position of a mesh
Maybe one of the methods that I find myself using the most often would be the degree to radians conversion method that there is to work with in this Object. Although it is not so hard to just do this with a simple expression because it is a such a common task of course there is a method for this in the Math utils method.
2 - The clamp and rand float methods
3 - Euclidean Modulo
As I have mentioned in the clamp example there is not just clamping, but also wrapping number values. In this example I am again doing more or less the same thing as in the clamp example, but now I am using the Euclidean Modulo method to wrap numbers rather than clamping them.
4 - The seeded random method
There is using the plain old Math random method and also many other methods that are based off of it. However all of these options are not deterministic in nature, that is that when called they will not give the same numbers each time. In other words some times I might want to have some kind of solution where I have random numbers in a range, but each time I reload the page I get the same set of random numbers. So then they are not really random, but predictable, yet they look kind of random if that makes any sense.
5 - The smoothstep function
The smooth step function will return a value between 0 and 1 that is a percent kind of value based on a video value to evaluate as the first argument compared to min and max values given as additional arguments. However the value returned will be smoothed or slowed down depending on how close the value is to the min or max value. A good way to go about getting an idea of how this method works might involve having a group of objects that all move by a fixed pixels per second value, then have another group that moves by a variable pixels per second value.
In this example I then have a helper function that will create a group of mesh objects with differing max pixels per second values in the user data objects of each mesh. I then have a simple update method that will move a group of mesh objects by the max value on each frame tick, and another update method that uses the Vector3.distanceTo method and MathUtils.smoothstep to get a variable pixels per second rate.
When this example is up and running group2 will just move at the fixed rate that is the max pixels per second value for the mesh object, while group1 will slow down and speed up based on distance and smooth stepping.
Also some of the things that come to mind are methods that I can not say that I use all that often such as an nth root method for example. That is an example of the kind of method that should not be in threejs because it is for the most part unneeded bulk. On the rare occasion that I do need an nth root method for whatever reason that is something that I can add by way of another library, or even a single stand alone method.