Addon. Produces almost infinite many time-varying geometries with functions

For the first time, I came across three.js in January 2016. Since September I have been working on this issue.

In three.js core elementary geometries are defined.

When designing my “Bumblebee Mara” I needed other shapes and produced them by deformation of sphere and cylinder.

Additionally inspired by ( @author zz85 <<< old link, no longer available, see revision 100)
I have programmed a three.js addon.

It produces almost infinite many time-varying geometries with currently only 9 properties, 18 functions and 2 arrays. This is easy by specifying the properties, functions and arrays.

UPDATE 2022 to three.js r136 see
Addon. Produces almost infinite many time-varying geometries with functions - #41 by hofk

example: gramophone

Forms library (excerpt):

As hofk I joined GitHub on April 25. The repositoriy there is THREEf.js. GitHub - hofk/THREEf.js: three.js addon, to produce almost infinite many time-varying geometries / buffer geometries with functions (cylindrical coordinates)
Some examples can also be found at codepen:

On my own site is a sandbox, where you can easily create the extended geometry. Currently only with Firefox.

The bumblebee is there at
Note! At the beginning I even called the variables in German. Later only the comments. This is because I have presented the things in a German forum. The link is at the top.

After a note from Mugen87 I will try to expand THREEf.js to BufferGeometry.

A further idea is to use polar coordinates instead of the cylinder coordinates r, u, v. Now the geometries are based on a cylinder default, then on a sphere.


This is excellent! I’m sure the community will put your plugin to much use!

Thanks :relaxed: @ TheCodeCrafter.

:new: Editable forms library on GitHub :new:

THREEf.js can be used to create very diverse shapes with the help of the functions. However, it is not always easy to find the appropriate formulas for a figure that you imagine.

So I changed the library from PDF to HTML. It is available on GitHub. Thus, one can make its forms available to other users.

Thanks to a large library, THREEf.js is easy to use for many users.

Create a geometry and add it to the library.

document.images[0...].src = "img/    .png";
parameterList[0...].value = "//0... Here is the right place for your example! \n ";

A short guide is at the end of the file:

// +++++ Do not destroy the following instructions. +++++   
Copy the last section, increase the indices and then describe your form in the penultimate section.
Set the number nnnn, a description and your author tag, possibly with URL.
If you copy the list of parameters into the string, replace the line break with \n
Copy your image to the img directory and use the pattern from above (fourDigits_name.type) for the name.
Take png (or jpg) images up to approximately 100KByte.

If the image is not square, change the height or width in your section:
document.images [index].width = "value" or document.images [index].height = "value"
See examples index 3 and 10, standard is 160 x 160.

I’m new to GitHub, I hope it works.

You can use to view live version of files on github.

Here’s your html file:

EDIT: rawgit has shut down. See here for a list of alternatives:

@looeee Thanks for your help.
I have not known all the important things around three.js.

If I extend THREEf to BufferGeometry, the question is whether indexed or non indexed.
Indexed has the advantage that the index calculations are almost identical to Geometry.
So I just have to add the write to the buffer arrays. When I query .isBufferGeometry and .isGeometry, I can effectively accommodate both variants in one method.

The user can then use Geometry or BufferGeometry without further distinction.

If I use non indexed BufferGeometry, this is a completely different system and I have to create it from scratch. This would only make sense if it is significantly more performant.

I found this answer from WestLangley (r73):

If this is still correct, I will use “indexed”.

I started with “indexed”. :relaxed:

With the calculation of the positions and indices for the individual triangles it proceeded fast. A wireframe mesh was present very quickly :watch: in the sandbox and the examples of the BufferGeometry.

But there are two problems, uvs and material index:

If not “circular open”, the last Geometry-vertices / BufferGeometry-indices are identical. For the uvs you need at BufferGeometry others! I could fix this by adding extra indexes. However, the uniform structure is already clearly disturbed.

(I wrote: The second problem is crucial.
Because each Geometry-face in THREEf can dynamically have a different material index, the Geometry-faces are constantly manipulated. For indexed BufferGeometry the material index is linked to the indices / positions via groups. The system is then completely mixed!

But even more problematic, then get two adjacent triangles with common index an identical material index. And this is not possible! ? :confused: )

I now have the definitions of BufferGeometry for cylinders, etc., viewed. Apparently, the groups refer to the indices and not the positions :question: Then it may be with indexed.

I still need to learn a lot about three.js!

TorusGeometry is a nice example for UV generation with BufferGeometry. Even if the geometry is closed it duplicates the last line of vertices. This is necessary in order to distinct texture coordinates. The duplication of vertices has also an effect on the respective indices. In other words, they are different for the first and last line of vertices.

@ Mugen87: Thanks for the hint.

That’s how I’m gonna do it.

I had already examined this duplication by the example of the sphere. There I wrote the numbers of the vertices to the wireframe:

In three.js I now searched for the groups. I’m interested in the CylinderBuffer.
There I found .addGroup( groupStart, groupCount, 0 ) for the Torso and 1, 2 for caps.
In the test, the cylinder showed three materials.

But with TorusBuffer these lines are missing. The multi material does not work there.

The search showed .addGroup () only with box, extrude, shape and cylinder?

Yes, not all geometries support multiple materials. The general philosophy of three.js is to keep things simple. Only some selected geometries use groups, where it actually makes sense. For example a Box has six clearly distinct surfaces that should be able to display different materials. But why would you want multiple materials on a sphere or torus? If users actually need these specific geometry data, they have to create them with 3D modeling tools like Blender. So multiple materials are not a must for procedurally generated geometries.

I understand and agree. With modeling tools or an addon :slight_smile:
I could possibly still think hemispheres as clearly distinguishable?

Since my circularly connected variant has no extra vertices, and I do not want to recreate the algorithm, I started with non indexed. But with a different procedure than to make the thing completely new! This works with identical code for Geometry and BufferGeometry.

I ask isBufferGeometry and then add the missing arrays as with Geometry (same name, internal use). Then add .addAttribute (‘position’, … etc.
After the calculation I write the values into the buffers, for example:

for ( var f = 0, p = 0; f < faceCount; f ++, p += 9 ) {		
		g.positions[ p ] =  g.vertices[ g.faces[ f ].a ].x; 
		g.positions[ p + 1 ] = g.vertices[ g.faces[ f ].a ].y; 
		g.positions[ p + 2 ] = g.vertices[ g.faces[ f ].a ].z; 			
		g.positions[ p + 3 ] = g.vertices[ g.faces[ f ].b ].x; 
		g.positions[ p + 4 ] = g.vertices[ g.faces[ f ].b ].y; 
		g.positions[ p + 5 ] = g.vertices[ g.faces[ f ].b ].z; 			
		g.positions[ p + 6 ] = g.vertices[ g.faces[ f ].c ].x; 
		g.positions[ p + 7 ] = g.vertices[ g.faces[ f ].c ].y; 
		g.positions[ p + 8 ] = g.vertices[ g.faces[ f ].c ].z; ...

This works quite well, see test:

You can switch between Geometry and BufferGeometry.

The BufferGeometry is always flat shaded. I have read some posts and looked at the three.js code to Geometry, DirectGeometry, BufferGeometry and (from …, .groups) intensively. Because non indexed is a “triangle soup”, smooth shading does not work. There is no information about the common points / connections - right?

If I have understood correctly, this is processed with Geometry in the renderer / shader.

If I try now indexed-BufferGeometry, I have to create (because of uv’s) extra vertices and the construction changes considerably, since I have no simple fixed geometry. The many functions must play together.

On the other hand, with the triangle soup, I can very easily create an exploded representation of the geometry.

How is the opinion :question:

BufferGeometry (was) not completely smooth
(edited see Bottom)

When I started with THREEf, I noticed that my self-made THREE.Geometry cylinder at the seam was not smooth.

The last vertices were however “exactly” in the angle 2 * Math.PI. That is why I then formed the last faces with the first vertices in connected geometries. This works perfectly with Geometry. With BufferGeometry there is however a problem with the uv’s.

To make my addon THREEf as uniform as possible for Geometry, BufferGeometry (indexed, non-indexed), I made some tests. With THREE.CylinderGeometry, the seam is smooth and vertexNormalHelper shows normal at the top oblique.

If I change to CylinderBufferGeometry ( is indexed ), there are two different normals at the seam. The seam is clearly visible. The normals at the top are horizontal.

In three.js I’ve seen that at function CylinderGeometry (… after fromBufferGeometry (… then this.mergeVertices () is executed with an epsilon of 0.0001.

This means that Geometry and BufferGeometry are not identical in appearance.

I am supposed to take BufferGeometry because it is more efficient. But I have a seam. Merge vertices also requires resources. My current method (non-indexed) of working with other arrays first and then writing to buffers is also not very efficient. My non-indexed BufferGeometry is always flat shaded.

(I am now quite uncertain how to do it. :thinking:)

EDIT Mai 21: I have now found: If I remove
the seam is smooth.

I probably have to test further variants!

Pictures of the seam (and German text):,html,js/3d-grafik-webgl-mit-three-js/?q=94096&pg=-1#94096

It took some time.:hourglass_flowing_sand:

Now the extension of THREEf to indexed and non-indexed BufferGeometry is finally finished. On GitHub: GitHub - hofk/THREEf.js: three.js addon, to produce almost infinite many time-varying geometries / buffer geometries with functions (cylindrical coordinates) . The old version is in THREEf_old.

If you do not need Geometry and BufferGeometry, you can delete the corresponding blocks.

That are

or in morphFaces

at the end of the functions

The new version you can test now on (firefox) .
There is a link basic examples / source where you can compare the three variants.

The old examples I have updated. Some figures are now created with BufferGeometry.

There is still a difference between the normals of Geometry and Buffer geometry. Using .computeVertexNormals (); in Geometry the normals are twisted to the left / right at the upper and lower edge.

This results (!waffled) from the different number (1 or 2) of faces left/ right. In BufferGeomety I have balanced this by doubling faces.

For example
vFace.push( fIdx * 3 );
if ( i === 0 ) vFace.push( fIdx * 3 ); // face double (equal number left and right)

Maybe later, I calculate the normal at Geometry itself.

Some more information (only in german language - my english is very bad) and pictures:,html,js/3d-grafik-webgl-mit-three-js/

1 Like

Inspired by the question
Rendering quad mesh and it's edges
I added a quad simulation.


Available on GitHub GitHub - hofk/THREEf.js: three.js addon, to produce almost infinite many time-varying geometries / buffer geometries with functions (cylindrical coordinates)
and test on

It works with Geometry and BufferGeometry.

For this I connected all vertices with a line in zigzag. In my test code this is good to see.

With BufferGeometry it works the same, is only slightly more confusing.:thinking:

lines Geometry: 300, 2358,
BufferGeometry: indexed: 580, 2570 , non indexed 1303, 2945

I have now expanded the vertexNumbersHelper to BufferGeometry.

Since non-indexed BufferGeometry has no vertices / indices, I use the internal array vertexPositions.

The triangles involved are stored in this array for each defined vertex. More specifically, the positions of the respective corners.

So I take the first entry for every vertex n.

vertexNumbers[ n ].position.set( … .vertexPositions[ n ][ 0 ] …

At the new possibility is now integrated.

The extended version is also available on GitHub GitHub - hofk/THREEf.js at master

THREEf.js is now ready. The final version 86.5 is on GitHub

As I wrote in the first post here, I now start with polar / spherical coordinates.

Some initial results are available:


there are other scripts. Variables and // comments in English, more precise explanations only in the German text.

I’m going to bring it to GitHub.


An alpha version of THREEp.js is available on GitHub.

p for polar / spherical coordinates

So far only indexed BufferGeometry is supported.

Two examples are added.

Here is another example:


// geometry
var parameters = {

  equatorGap: 0.05,
  bottomCircle: 7,
  withBottom: true,
  topCircle: 12,
  withTop: true,
  rPhiTheta: function( u, v, t ) { return  1.5 + Math.sin( 4 * Math.PI * u )  },


Nice guys! Keep up the great work!

THREEp.js. - an extended alpha version is now available on GitHub

  • It works with three.js r87.
  • The spherical wedges can be closed at the side (default).
  • The equator gap is now available as a function.

With the equator gap - now as a function - a small monster opens and closes its mouth.
With parameter t - Time.

screenshots exampleA2. html



var parameters = {

equator: 4,

equatorGap: function( u, t ) { return  0.5 *( 1 + Math.cos( 6.28 * u)) *( 0.5 -  u )*( 0.5 -  u ) * ( 1 + Math.sin( t ) ) },
stretchSouth: function ( u, v, t ) { return  ( 1 + Math.cos( 6.28 * u)) *( 0.5 -  u )*( 0.5 -  u ) * ( 1 + Math.sin( t ) ) },

wedges: 11,
usedWedges: 8,

topCircle: 7,
withTop: true,

bottomCircle: 3,
withBottom: true,


:new:I created a sandbox for THREEp. js.:new:

It is available with the latest alpha version on GitHub and on my site.
On is now a selection: THREEf or THREEp.

A nasty bug got me annoyed and took time. He’s been in there a little longer. But it only became visible in certain parameter constellations. So he was able to slip through for some time. The positive side effect is that the vertexNumbersHelper function is now extended to vertexFaceNumbersHelper. Either vertices or faces or both.

The squeeze function is available. It is solved similar to unrolling with the cylinder.


More detailed explanations can be found in the German forum.,html,js/3d-grafik-webgl-mit-three-js/

This is quite cool! It has so many uses! Congratulations sir, you are a genius.