Parametric modeling using tree method

Continuing to think about the idea of ​​parametric modeling and developing the previous idea: Parametric modeling from primitives (cube, sphere...) and animation

I decided to do it through a function. Where the vertex ID will be passed at the input. And at the output it should return the vertices, normals, UVS and the IDs of the next vertices. Thus, calling this function will build a model tree.

In essence, the model is built by arrows. From point to point. Three points form a triangle. This is a great idea!

Two hours later. Implementation of the cube function.

        let box = function(vId, fId){ // vertexId, prevousId
            const vert = [[0, -1, 0], [-1, -1, -1], [1, -1, -1], [1, -1, 1], [-1, -1, 1], [-1, 1, -1], [1, 1, -1], [1,  1, 1], [-1, 1, 1]];
            const uvs = [[7, 7], [0, 0], [1, 0], [1, 1], [0, 1], [0, 0], [1, 0], [1, 1], [0, 1]];

            if(vId == 0){
                return { vert: [0, -1, 0], norm: [0, -1, 0], uv: [.5, .5], id: [1, 2, 3, 4] };
            } else if(vId < 5){
                return { vert: vert[vId], norm: [vert[vId][0] * 0.5773502691896258, vert[vId][1] * 0.5773502691896258, vert[vId][2] * 0.5773502691896258], uv: uvs[vId],
                    id: fId == 0 ? [vId != 4 ? (vId + 1) : 1] : [vId + 4] };
            }else if(vId < 9){
                return { vert: vert[vId], norm: [vert[vId][0] * 0.5773502691896258, vert[vId][1] * 0.5773502691896258, vert[vId][2] * 0.5773502691896258], uv: uvs[vId],
                    id: fId < 5 ? [vId != 8 ? vId + 1 : 5] :
                    Math.abs(vId - fId) == 1 ? [vId != 8 ? vId + 1 : 5] : 0
                    //id: fId < 5 ? [fId != 4 ? (fId + 1) : 1] : []
                    //    id: fId < 5 ? [vId != 5 ? (vId - 1) : 8] : [9]
                };
            } else if(vId == 9){
                return { vert: [0, 1, 0], norm: [0, 1, 0], uv: [.5, .5], id: [] };
            } else if(vId == undefined){
                return { verts: 10 };
            }
        }

This is impossible to use. It is extremely difficult to describe logically. A vector language is needed here. Helping to build connections between points.

Are there any ways to improve the current approach? So that it can be used.

I am thinking about the level method. When the function will return a list of points for the level. For example, a cube is two levels of 4 points.

I’m not native English speaker and I cannot understand what you try to do. It might be good to add an illustration of what you are trying to achieve, with arrows between input vertices and output vertices.

Maybe if you build a DCEL over your mesh, you could easily traverse the net topologically (e.g. going from any vertex to any neighbour vertex; or finding all faces with a common vertex; or finding all faces connected to a specific face; and so on).

The code above looks too fixed (bound to cube’s topology and how its vertices are arranged by Three.js), i.e. it would be hard to extend it to other meshes without significant efforts.

2 Likes

We build a cube model. The function returns a sequence of pointers to the next vertex. We build triangles on them.

0 1 2
1 2 6
2 6 7
6 7 9
0 2 3
2 3 7
3 7 8
7 8 9
0 3 4
3 4 8
4 8 5
8 5 9
0 4 1
4 1 5
1 5 6
5 6 9

Yes, the problem is that even for a cube the code is too complex. Building a sphere would be a tough test for the brain.

However, the logic behind using this function is incredibly simple:

const verts = box().verts;

for(let i = 0; i < verts; i ++){
   const result = box(i);
   this.addVertNorm(...result.vert, ...result.norm);
   this.addUv(...result.uv);
}
this.makeThreeIndex(options, undefined, 0, 0);


    makeThreeIndex(options, vId0, vId1, iteration){
        const result = box(vId1, vId0);

        for(let i = 0; i < result.id.length; i ++){

            // There are 3 points
            if(vId0 != undefined){
                    this.addIndex(vId0, vId1, result.id[i]);
            }
            this.makeThreeIndex(options, vId1, result.id[i], iteration + 1);
        }
    }

Hey just wanted to see if you are aware of three’s ParametricGeometry class?

Here’s a sphere function (generated by gpt)

function parametricSphere(u, v) {
    const radius = 1.0; // Radius of the sphere
    const phi = u * Math.PI * 2;        // azimuthal angle (around the y-axis)
    const theta = (v - 0.5) * Math.PI;  // polar angle (from top to bottom)

    return new THREE.Vector3(
        radius * Math.cos(theta) * Math.cos(phi),
        radius * Math.sin(theta), // y-axis is vertical
        radius * Math.cos(theta) * Math.sin(phi)
    );
const geometry = new THREE.ParametricGeometry(parametricSphere, 32, 32);
}
3 Likes

Whoa cool.. didn’t know about that class. TIL :smiley:

1 Like

That sphere with the “hexagonal” hole is ParametricGeometry: OMNIVISOR [mechanical eyeball]

3 Likes

In r171 it’s there:

4 Likes

Here my parametric cube, maybe it helps you. Try with resolution 100, 200, 300.

https://codepen.io/Spiri0/pen/zxxvqYb?editors=0010

I’ve been thinking about making this an official threejs example.

1 Like