This week I was learning more about how to work with a buffer geometry in threejs when it comes to the various attributes that make up such a feature in threejs. There is the position attribute in the geometry which is the attribute that holds the current positions of all the points in the geometry for example.
So I think it might be a good idea to wrap this week up with a few simple threejs project examples that have to do with mutating the position attributes of a geometry made with one of the built in geometry constructors. One such constructor to work with when it comes to this is the sphere geometry constructor which is just one of many options of course but that is one of the main ones that come to mind so I will go with that one. It then might prove to be an interesting learning experience to work out some methods that have to do with changing the geometry a little, as there is a lot to work with in the threejs library over all for doing so such as the various methods of the Vector3 class.
In this post then I will be going over my first quick example that has to do with a helper method that changes the position of a point on a sphere. The process of doing so is not always so easy as there is not just one point that needs to move but all points of all triangles at that point in space actually. So this might prove to be the kind of example that I might come back to now and then in order to find new ways to go about doing this.
It might be a good idea to read up more on the buffer geometry class in general, as there are a great number of properties and methods in an instance of buffer geometry that you should be aware of before getting into an example like this. The main feature of interest when it comes to changing the points in a geometry would be the position attribute of a geometry created with one of the built in geometry constructor methods.
I have wrote a number of blog posts on the Vector3 class and I have to say that there is a lot of useful tools in that class that can help with the mutation of the position attribute of sphere geometry. There is the normalize and multiply scalar methods that can be used to change the vector unit length of each vertex in the sphere for example. There is also making use of the apply Euler method with the Euler class to change diction of each point in the sphere.
The state of the position attribute might be a linear array of numbers, but there is also getting into how to convert that to an array of Vectors, or create a vector3, use the class methods to do what I want, and then mutating the array of the position attribute. I will be going over some source code examples of this here, sure, but I would not stop at this post when it comes to reading about this sort of thing.
The source code for this example and many more is on github in my test threejs repo. I have learned a great deal more about threejs and buffer geometry, as well as buffer attributes sense then, so I now have an r1 example that I will be writing about first and foremost in this post. In addition I also have notes for a few additional future revisions of the example that I might get to at some point sooner or later that are stored in a to do list of the for post folder that corresponds with this blog post.
When I wrote this post I was using threejs version r127, and the last time I came around to do a little editing I was using r140. When I first wrote this post I has what I was referring to as r0 of a sphere geometry mutation example.
For revision r2 of the sphere mutate threejs example I wanted to do somehtig about the seam that I was dealing with in r1 and that is the main thing that I resolved in this revision. I wanted to make a number of other improvements as well thorough such as making a module form of what I have worked out thus far when it comes to this sort of thing, and also have more that one demo of this new module form of the project example.
There are two main pubic methods for the module that are of interest, the create method and the update method. The create methods will create and return a mesh object with a geometry made with you guessed it the SphereGeometry constructor, as well as the use of the Phong Material when it comes to skinning the geometry. In addition to this I am also setting up some properties for the user data object that will be used by the update method. If you are not familiar with the user data object it is just a standard place to park user defined properties to any object3d based object such as a mesh object. In this case I am using it to park a starting position attribute state as well as a reference to the current state as well.
The update method is then what is used to update the state of the position attribute of the sphere geometry based on what is given in terms of a for point and for pole function.
For my first demo of this new sphere mutate module I made a demo that is like that of what I worked out for the r1 form of this threejs example. That is that I just move all the points in and out to and from random vector unit lengths.
I wanted to make at least one example that makes use of Math.sin as a way to adjust the geometry of a sphere. This then results in a cool wave like effect that I had in mind when starting to make this.
Another idea that I had is to just have some kind of map system as a way to define what the changes in unit length should be.
For r1 of my sphere mutation threejs example project I wanted to just make an example that makes better use of buffer attribute class features in place of what I made first in r0. If you still want to check out the older code for whatever reason it is down below in a latter section in this post as I am thinking that I will want to always pull the latest revisions up to the top.
Anyway the main feature of interest here is the create new vectors helper function that will create and append arrays to the User Data object of a mesh object based off of the original state of the position attribute of the buffer geometry of the sphere. The goal here is to create to arrays of vector3 objects, one of which is for each point in the original position attribute state, and the other is a new state of random points to lerp to. In my later update geometry method I will be using the lerp method of the Vector3 class to transform the starting state of the sphere geometry to this new set of points that are random vector unit lengths but with the same direction as the original points.
I then have a special create mesh helper function that will create a mesh object with a sphere geometry and also set up the pos_base property of the user data object with a clone of the starting state of the sphere geometry. On top of that I am also calling the create new vectors helper for the first time which will of course set up those additional user data object properties that i want to have at the ready for updating things. Speaking of updating things the final helper function of interest here then is the update geometry helper function that I will be calling in the main update method of the animation loop for this example. In this method I am looping over each point in the sphere geometry and using the lerp method to update each point of the sphere to a position that is between the state point and the new random vector unit length point based on a given alpha value.
So now for the older r0 source code of this threejs example where I am changing the position of a point at the top of a sphere. In this example I started out with by set vertex helper method that I worked out in a previous example this week that had to do with the position attribute in general. This helper makes use of the geometry index property as a way to help change the right position data in the position attribute of a given geometry. When using the THREE.SphereGeometry constructor the return geometry will contain this index property as the constructor sets up a position attribute with a lower than usual number of points by reusing points. With certain other geometries there may not be an index, or there are ways of making a sphere geometry not indexed but maybe that is all a matter for another revision of this example or a whole other post.
I then have my update sphere top point helper method where I just pass a sphere geometry as the first argument, and then the y value for the top point of the sphere. So in other words this is a method where I can pull the top point of a sphere up or down along the y axis. Inside this helper method I get a reference to the position attribute of the sphere geometry, and then I also create a new position object that will be used for all points of all triangles that are at that point. I then use the set vertex helper to set the position of all of these points in the body of a while loop. When it comes to setting up a condition for getting out of the while loop I have found that I can use the width segments parameter as a way to create a value that seems to work well with just about any sphere that I pass to it.
I then set up a scene object, renderer and camera just like with any other threejs example. I then create a mesh object that will of course use the THREE.SphereGeomerty constructor and add the mesh to the scene. I then also have a main animation loop for this example and in the body of that loop I am calling my update sphere top point method that will change the position of the top point of the sphere over time.
This example might have turned out into a decent starting point at least when it comes to just playing around with sphere geometry, however there are so many other things that come to mind that I would like to work out and have a better understanding in place still. Some things that might help would be to just loop over all the points in a geometry and return all the points that share the same point in space. That way I can just call that method and move all points that are at that location which might prove to be a very helpful tool when it comes to doing things like this.
So then that will be it for now when it comes to this threejs example on mutating the values of a position attribute of a geometry of a sphere. Thus far I have to versions of this example, but I have many more ideas for sure when it comes to this sort of thing. There is also doing what I am doing here but with one of the other built in geometries such as a plane geometry, or maybe even better yet a custom geometry that is just three points in space when it comes to focusing on cretin fore basics better.
There as a whole lot more that comes to mind that I have not even wrote down in terms of additional similar ideas for sphere mutation projects. I will still want to work out at least a few more basic core examples though before I start to go nuts with this and start making a whole bunch more revisions, maybe even going to far as making some kind of module that helper abstract away much of what I have code to learn thus far about sphere geometry and then just make a whole bunch of demos for each future revision.