I would like to start at least one if not more threejs project examples that have to do with setting up the uv map of a cube created with the THREE.BoxGeometry constructor in threejs. By default the geometry will have a uv map, it is just that it will use all of the given texture for each face of the cube.
There are two general ways of doing what I would like to do with cubes here. One way would be to mutate the uv attributes over time so that the locations in a single texture change. The other way would be to set up the uv attribute once so that the cube will always used fixed locations of the canvas, then use a canvas element as the texture, and update that texture as needed. In this post what I currently have is centered around the later rather than the former, but that might change with future revisions of this when and if I get to it.
Although I will not be getting into detail with every little thing there is to know about before hand, I will write about at least a few things in this section. Also I will of course link to additional relevant posts where and when needed in which I will get into detail.
A long time ago now I wrote a blog post on canvas textures in threejs, however this is also a post that I find myself editing often. Anyway to get to the point the cube uv module that I am writing about in this post works on top of my canvas module that I write about in that post. I could have baked some code into the cube uv module alone, but I am thinking that this project will be one if not many projects in which I work on top of that module.
I also wrote a blog post on the texture loader in threejs, and with some of the demos of the module I am using the canvas loader abstraction that I write about in that post. This is not as important as the canvas module, and I also have some demos in which I am just using the texture loader directly. Still it is nice to abstract some of that away to make the demos a little lighter in terms of the over all volume of code.
This is not at all a getting started post on the uv attribute of buffer geometry that has to do with defining the offsets for areas of a texture that are to be rendered to a face of a geometry such as but not limited to a cube.
There is a whole lot to be aware of when it comes to buffer geometry in general. The main focus that is relevant here is the uv attribute, but there is also the position and normal attributes of geometry as well. On top of that there is also index and none indexed geometry, groups, and the various properye8s and methods of the Buffer geometry as well as buffer attributes classes along with way more.
The source code for the modules as well as the examples can be found in the for post folder for this post in my test threejs repo on Github. The source code for the canvas module that I am working on can also be found there in the for post folder for my post on canvas textures. Also the source of the texture module that I use for some of the examples here can be found in that repo as well.
The version of threejs that I was using when working on this was r146.
This is the source code of the first version of my uv map cube module. The main features of interest here are the private helper functions that I am using to get the desired uv values that I will want to set for a given face index, cell index and grid size for the texture. When it comes to the first method up top called getUVData I pass a uv attribute reference along with a face index, cell index and grid size to get an array of index values along with u and v values to set for that index to get a desired outcome.
For this first version of the module I am thinking in terms of breaking down a texture into a number of divisions that are the same for both height and width. This is what the grid size argument is about as that is the number of divisions that I would like to have. You see the resolution of the textures that I use always need to be a power of 2, and they always need to be square. However I can divide up the area of the texture anyway that I would like, and for now I am thinking just in terms of a grid that is 4 by 4 by default. So then if I use a texture that is say 128 by 128, then the resolution of each cell will be 32 by 32.
So then if a 128 by 128 resolution texture is divided up into 32 by 32 cells there will then be cell index locations of each of these cells. In this case there will be 16 cells and if we are talking zero relative numbers that means the index range will be from 0 to 15. The face index value then is the index for a face on a cube and the range for that would be 0 to 5.
When I create an instance of getUvData I will then want to use this to set the state of the uv attribute. For this I have my setUVData helper where I pass the uv that I will like to mutate, along with the uvData area created with my getUVData helper, and then and order array that will default to [0,1,2,3] which so far seems to work okay, but I might need to adjust when it comes to setting the rotation of the uv points. However with this project there is also doing a rotation when it comes to drawing to the canvas texture that I am using as well which is what I prefer for this revision of the module at least when and if I need to do so even to begin with.
I then have my public api that contains a create method and a single draw face method. The create method will set up and return a mesh object that uses a geometry created with the THREE.BoxGeometry constructor, and also with the THREE.MeshPhongMaterial. However this is not just any mesh object as I am using the user data object of the object3d class based mesh object to store an instance of an object created with my canvas module as well as other data that I will be using to update the state of the texture that is used for the map and emissive map options of the phong material.
I then have a draw face method that will allow me to draw to a given face of a given mesh object that was created with the create method of this module. I use it by passing the mesh object as the first argument, and then a face name of the cube that I would like to draw to. I can then pass an object that contains info in terms of the source image to use, along with 2d offset, with and height values to use. So then this method will just draw once face per call.
This is what I have together for a hello world of this project. Here I am setting up a typical threejs project scene by creating the scene object, camera, and renderer. I like to work on Raspberry PI OS actually so I am going with the web gl 1 renderer to avoid problem that I have noticed starting with r141 which is why I was sticking with r140 for a while.
So when it comes to the sources images that I will be using I am again using my canvas module and with that the built in rnd draw method that just creates a random texture for a given grid size in this case I am setting the grid size to 16. I have then made a make canvas options helper that has all the settings that I want when making my canvas object and I am then just calling that for each image that I will be using only making changes for the palette option.
I then create my mesh object with the create method of the uv map cube module and then use the draw face method to update what faces to what faces to what. This time I am only updating two faces of the cube to image 1 while leaving everything else to the default image used which is image 0.
In this example I am using an external image as the texture rather than using canvas elements. To do so I am making use of the threejs built in texture loader as a way to go about loading just a single image for now. However I am still doing so in a way in which things should still work well when it comes to using more than one texture also.
Here I am once again using external image assets but now I am using my texture module however now I am using a texture module that I would out for my post on the threejs texture loader. What I would out in that project might be something that I should build into this module in future revisions, or yet again maybe not as it is something that I might want to just develop and maintain when it comes to working with textures in general actually. In any case by pulling the code that has to do with loading textures they way that i would like to lad them into a separate file that helps to reduce the complexly of the demo here which is nice.
This module seems to work okay so far as of r0 all ready have the basic idea of what I wanted working. When and if I get around to it I will still like to make a few changes of course when it comes to any possible future revisions of this project. For one this I would like to have at least a few more options when it comes to how I go about dividing up a sprite sheet that I use to skin the cube. Although I am going in the direction of just setting the uvs once I might still want to add some methods that give me greater control over updating the uvs over time and maybe not so much the texture that I am using.