When it comes to adding content to a scene for the most part one will want to make use of Mesh objects, and with that geometry and materials that work well with such objects. However when it comes to first starting out learning how to make custom geometry, and for other various reasons one might want to make use of an alternative such as THREE.Points. The THREE.Points class is a way to create a content object that will work well with a geometry that might just have a position attribute and nothing else.
The position attribute is the first and foremost attribute that one will want to work out when making a custom geometry as it is the actual points in space. So often I might start out using THREE.Points when making a custom geometry as the first steps is just figuring out the position and order of the points in space. Once I have the position attribute worked out well I can then move on to working out the various other attributes that will get the geometry to work well with Mesh Objects.
There are a number of other reasons why one might want to use the THREE.Points class. One thing that I find myself using it for all the time is to get a visual idea of what is going on with the state of a Curve Path for example. In any case in this post I will be writing about a general overview of the THREE.Points class, and while I am at it write about a lot of other things that will come up in the process such as position attributes of buffer geometry objects.
The THREE.Points class is a great way to get started with making custom buffer geometry objects, the class of which one might want to read a whole lot more about. I say that because when it comes to making a custom geometry work well with THREE.Mesh there is not just working out a position attribute, but also normals, and uv attribute as well in order to get everything looking okay when it just comes to a simple static model.
However when it comes to THREE.Points it is just the position attribute alone that is of interest which does help to simply things. Again if I just want to work out a simple static model that will work okay with THREE.Points at least. There are additional attributes that I might want to add on top of these such as a color attribute, and also there is still getting into morph attributes with these kinds of geometry objects when it comes to looking into how to animate things.
The source code exmaples that I write about in this post can be found in the corresponding for post folder in my test threejs repository on Github. This is also where I park the source code for my many other blog posts that I have wrote thus far as well. On top of the latest revisions of the examples that might in some cases be newer then what I have here I also have notes and todo lists for any future edits on this post. With that said if you think something needs to change or be added in a post such as that and you are on Github that would be a good place to make a pull request.
When I first wrote this blog post I was using r146 of threejs and I am using three.min.js rather than three.module.js. There is a lot that will be changing up ahead when it comes to future revisions of threejs, also if you are all ready using JSM over old script tags these examples will not work all ready. Because threejs is a fast moving project where things are always being removed or changed it is a very good idea to always be mindful of what revision of threejs is being used and how when studying source code examples on the open web.
To start out this post in this section I will be getting a few basic examples out of the way. The general idea here with THREE.Points is very similar to that of THREE.Mesh in that I need to create a geometry, and then pass that geometry as the first argument when calling the THREE.Points constructor function. However when it comes to passing a material as the second argument I can not make use of any of the materials that are made for mesh objects. Aside from that once I have a points objects I can add that object to my main scene object, just like that of any other Object3d class based object.
Just like with all my other posts on threejs I have to start somewhere, and for this basic example of the THREE.Points class I will be starting out with a very basic hello world type example of THREE.Points. Just like with any other threejs example I need to start out with a scene object, camera, and renderer. Once I have the usual set of objects I can then create a THREE.Points object and add that to the scene. When it comes to doing so I need a geometry and for this first example I am just making a box geometry wit the built in THREE.BoxGeometry constructor and passing that as the first argument when calling THREE.Points.
After I create my Points object and add that to the scene I then position my camera and call the render method of the webgl renderer passing the scene object, and the camera to render the current state of this scene. The end result is then eight points in the canvas, or at least that is what it looks like anyway, in reality it is much more when it comes to the state of the position attribute. More on this in this section as I at least touch base on the position attribute of buffer geometry objects, and I think I should also have a more advnaced section in this post on this subject as well.
For this next basic demo I will be making use of a PlaneGeometry, and also demo what happens when using Edge Geometry to create a another geometry from the plane geometry. This time I am adjusting the size of the plane geometry to 10 by 10, but I am also passing 10 by 10 when it comes to the segments as well which results in a kind of grid like layout compared to the default values for the number of segments that are 1 by 1. However I am making two points objects in this demo one of which makes use of the plane geometry alone, and another that makes use of an edge geometry created from that plane geometry.
One of the draw backs with using THREE.Points is that I can not use the various mesh materials as this is a Points object rather than a Mesh object. When it comes to material options with points there is just one option which is the THREE.PointsMaterial. As with any material there is knowing what there is to work with when it comes to the base material class such as the transparent and opacity options.
There are a few options on top of the base material class when it comes to what the Points Material adds on top of it. For the most part the two main options of interest are size and color. With that said in this demo I am just creating two materials, one of which I am setting the color to red, and also setting some values for opacity as well. The other material I am setting to a lime color, with a smaller size. I am then creating two points objects that make use of two geometries for the sake of comparison.
There are a lot more features to write about when it comes to the points material, as well as base material class features that will still work with the points material. However this is very much the basic section, much of what there is to cover with that will need to be explored in another section, or whole other post.
Now that I have covered a lot of basic hello world type examples of THREE.Points I think I should have at least one basic example involving the position attribute of a buffer geometry. Nothing to advanced yet as this is still very much a basic section, but I think I should at least mention a thing or two about the position attribute here. As I covered in the very first example in this section, it looks like there are eight points in a geometry created with the THREE.BoxGeometry class. However if you take the time to inspect the Box geometries position attribute you will find that there are actually 24 points. Getting into depth as to why that is might prove to be a bot to much for a basic example, however I think that I should at least have a little code example that shows that this is indeed the case.
So then for this example I once again create a Box Geometry, with the same set of arguments as in the first basic example. However now I am going to use the get attribute method of the buffer geometry class to get a reference to the position attribute of the geometry. If one takes a look at the count of the position attribute they will find that the count of points is indeed 24 if the segments argument are left to the default as I am doing in this example. I can then use this count value as a way to know how many points there are to loop over when making say a while loop to do so. In such situations I can use buffer attribute methods such as getX or setX to get and set values for each axis of each point in the position attribute. For this example I just want to change the x values to make it clear that there are in fact way more points then eight in the geometry.
For this section I am going to be writing at least a thing or two about the set from points method of the buffer geometry class. I think that it is a good idea to have at least a few demos that make use of this feature when it comes to writing a post o TREE.Points as I would say it is a closely related topic. The general idea of the set from points method is that it is a quick way to create a buffer geometry from an array of Vector3 objects. So one can create an array of points in space my making a whole bunch of Vector3 objects, pushing each of them to an array, and then just simply pass this array to the set from points method. The end result will then be a geometry with a position attribute crated from this array of vector3 objects. A geometry such as this will not work so well when used with mesh objects, but when it comes to lines and points it will work just fine.
In order to get started with the set from points method I first need an array of Vector3 objects. To help with with this example and every additional example I will be making in this section I have a helper function that will just return an array such as this by passing a count of points that I want and a function where I can pass some logic to apply to each point that will be pushed into the array of points. I then also have a helper function where I pass an array of vector3 objects and get a geometry that is created from that array of vecotr3 objects by making use of this set from points method. Once I have the geometry I can then create the THREE.Points object by just passing the returned geometry as always.
The set from points method works great for creating a geometry to begin with, but it is not the best tool for updating a geometry over and over again. I have updated geometry this way I have found that I run into loss of context problems. I have not looking into the source code of how the set from points method works, but it might work in a way in which the size of the position attribute can be changed each time it is called which might not always be such a good thing away. In thing that it is often better to just think in terms of a fixed number of points and then update the state of those points as needed over time.
A more advanced topic with geometry in general would be the groups property of a geometry which is not to be confused with the THREE.Group class as that is a kind of object3d class based object for grouping objects like THREE.Points and many others into a single parent object. The groups property of buffer geometry however is what will come into play when I am in a situation in which I will want to use more than one material for an object. When it comes to mesh objects for example I might want to use the Lambert material for a wood surface, but the phong material for a metal surface. Although this sort of thing might come up more often with mesh objects the same can very much be done with points as well. In other words there is not just giving a single instance of THREE.PointsMatreial when calling THREE.Points but rather an array of materials.
When working with an array of materials there must be some kind of way to set what material index value should be used for what range of points in the geometry. With that said that is where this groups property, and the use of various other related buffer geometry class methods will come into play. The groups property is a collection of objects that contain a material index value and then additional values that can be used to set a range to use this material index. I have wrote a main blog post on this subject of material index vlaues and groups, however I think I should have at least a few demos in this post as well.
There is once again starting out with just a simple box geometry, but now just use an array of materials rather than just one. What is nice about the Box geometry class is that the geometry that is created all ready has a group property set up for me. This then makes getting started with this all the more easy as I really do just need to give an array of materials and that is it. For this kind of situation I can then give six materials, one for each side, and the end result is that I can adjust the color, size, and any other materials options on a side by side basis.
For each of my blog posts on threejs I like to make at least one if not more short little demo videos to embed into the content of the post to help get a better visual idea of what the over all blog post is about. So for this section I will be writing about what I have together thus far for these kinds of source code examples.
I would like for my first video for this post to make use of morph attributes and vertex colors. With that said I worked out this quick demo based on the source code from one of the official threejs examples on morph attributes. This is a pretty cool demo in which the geometry of a box geometry is being mutated into a sphere like shape and then back again by adding a position key to the morph attributes property of the box geometry that will contain an array. There is then creating an attribute that will be the new set of position values to morph to.
That will be it for now then when it comes to a general overview of THREE.Points in threejs. That is until the nest time I come around to do a little editing on this post when and if I get around to it. I would like to refine and expand a whole lot more on a wide range of other things that I did not get the time to do so with. However maybe much of that would be better done in additional posts on the subjects of points in threejs.