Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Volumetric NURBS #27601

Merged
merged 10 commits into from
Jan 23, 2024
Merged

Volumetric NURBS #27601

merged 10 commits into from
Jan 23, 2024

Conversation

mmoelle1
Copy link
Contributor

Related issue: none

Implementation of volumetric (aka tri-variate) NURBS

Tri-variate NURBS are parametric volumes with variables (u, v, w). Extending the example webgl_geometry_nurbs.html a volumetric NURBS geometry can be generated as follows

        const nsControlPoints = [
        [
          [
            new THREE.Vector4( - 200, - 200, 0, 1 ),
            new THREE.Vector4( - 200, - 200, 100, 1 )
          ],
          [
            new THREE.Vector4( - 200, - 100, 0, 1 ),
            new THREE.Vector4( - 200, - 100, 100, 1 )
          ],
          [
            new THREE.Vector4( - 200,   100, 0, 1 ),
            new THREE.Vector4( - 200,   100, 100, 1 )
          ],
          [
            new THREE.Vector4( - 200,   200, 0, 1 ),
            new THREE.Vector4( - 200,   200, 100, 1 )
          ]
        ],
        [
          [
            new THREE.Vector4( 0, - 200, 0, 1 ),
            new THREE.Vector4( 0, - 200, 100, 1 )
          ],
          [
            new THREE.Vector4( 0, - 100, 0, 1 ),
            new THREE.Vector4( 0, - 100, 100, 1 )
          ],
          [
            new THREE.Vector4( 0,   100, 0, 1 ),
            new THREE.Vector4( 0,   100, 100, 1 )
          ],
          [
            new THREE.Vector4( 0,   200, 0, 1 ),
            new THREE.Vector4( 0,   200, 100, 1 )
          ]
        ],
        [
          [
            new THREE.Vector4( 200, - 200, 0, 1 ),
            new THREE.Vector4( 200, - 200, 100, 1 )
          ],
          [
            new THREE.Vector4( 200, - 100, 0, 1 ),
            new THREE.Vector4( 200, - 100, 100, 1 )
          ],
          [
            new THREE.Vector4( 200,   100, 0, 1 ),
            new THREE.Vector4( 200,   100, 100, 1 )
          ],
          [
            new THREE.Vector4( 200,   200, 0, 1 ),
            new THREE.Vector4( 200,   200, 100, 1 )
          ]
        ]
        ];
        const degree1 = 2;
        const degree2 = 3;
        const degree3 = 1;
        const knots1 = [ 0, 0, 0, 1, 1, 1 ];
        const knots2 = [ 0, 0, 0, 0, 1, 1, 1, 1 ];
        const knots3 = [ 0, 0, 1, 1 ];
        const nurbsVolume = new NURBSVolume( degree1, degree2, degree3, knots1, knots2, knots3, nsControlPoints );

Since ParametricGeometry does not support tri-variate objects arbitrary slices of the NURBS volume can be visualised as follows:

        const map = new THREE.TextureLoader().load( 'textures/uv_grid_opengl.jpg' );
        map.wrapS = map.wrapT = THREE.RepeatWrapping;
        map.anisotropy = 16;
        map.colorSpace = THREE.SRGBColorSpace;

        function getSurfacePointFront( u, v, target ) {

          return nurbsVolume.getPoint( u, v, 0, target );

        }

        function getSurfacePointBack( u, v, target ) {

          return nurbsVolume.getPoint( u, v, 1, target );

        }

        const geometryFront = new ParametricGeometry( getSurfacePointFront, 20, 20 );
        const materialFront = new THREE.MeshLambertMaterial( { map: map, side: THREE.DoubleSide } );
        const objectFront = new THREE.Mesh( geometryFront, materialFront );
        objectFront.position.set( - 200, 100, 0 );
        objectFront.scale.multiplyScalar( 1 );
        group.add( objectFront );

        const geometryBack = new ParametricGeometry( getSurfacePointBack, 20, 20 );
        const materialBack = new THREE.MeshLambertMaterial( { map: map, side: THREE.DoubleSide } );
        const objectBack = new THREE.Mesh( geometryBack, materialBack );
        objectBack.position.set( - 200, 100, 0 );
        objectBack.scale.multiplyScalar( 1 );
        group.add( objectBack );
@Mugen87
Copy link
Collaborator

Mugen87 commented Jan 22, 2024

Do you mind updating webgl_geometry_nurbs by adding a new mesh to demonstrate the new NURBSVolume module?

@Mugen87 Mugen87 added this to the r161 milestone Jan 22, 2024
@mmoelle1
Copy link
Contributor Author

@Mugen87 Thank you for the suggestion, I will do. There is one small problem. As described in the commit message ParametricGeometry only supports bi-variate geometries. I can update webgl_geometry_nurbs to have multiple slices as I did in the commit message (and for testing), e.g., the six surfaces of a cube. Or is there a tri-variate version of ParametricGeometry?

@Mugen87
Copy link
Collaborator

Mugen87 commented Jan 22, 2024

Or is there a tri-variate version of ParametricGeometry?

No there isn't. But as a start the mentioned code example would be good.

@mmoelle1
Copy link
Contributor Author

mmoelle1 commented Jan 22, 2024

@Mugen87 Would this example be sufficient? If so, I will implement it into webgl_geometry_nurbs and update the PR.

@Mugen87
Copy link
Collaborator

Mugen87 commented Jan 22, 2024

LGTM!

Maybe you can add a comment that explains why several instances of ParametricGeometry are created and what they represent.

Expanded NURBS example to NURBSVolume objects.
Added missing include
@mmoelle1
Copy link
Contributor Author

I have updated webgl_geometry_nurbs as requested.

@Mugen87
Copy link
Collaborator

Mugen87 commented Jan 23, 2024

Do you mind updating the E2E screenshot? Otherwise the CI fails.

You can do that with the following command:

npm run make-screenshot webgl_geometry_nurbs
@Mugen87
Copy link
Collaborator

Mugen87 commented Jan 23, 2024

Do you mind updating the screenshot one more time? It seems the new screenshot does not honor the changes I have added to your branch (see c12b41f).

@mmoelle1
Copy link
Contributor Author

I took the screenshot too quickly :-) Shot be fixed now. Thanks for implementing the changes.

BTW, I would not mind working on a tri-variate ParametricGeometry but I might need some help from three.js experts.

@Mugen87
Copy link
Collaborator

Mugen87 commented Jan 23, 2024

Feel free to give this a try. Now with having NURBSVolume an enhanced version of ParametricGeometry makes sense.

@Mugen87 Mugen87 merged commit 02d41f8 into mrdoob:dev Jan 23, 2024
11 checks passed
@mmoelle1
Copy link
Contributor Author

@Mugen87 There is another feature that I would like to contribute to three.js - adaptive splines. More precisely, truncated hierarchical B-splines (THB). Their basic definition is like NURBS but without the weights. On the plus side, THB splines make it possible to refine the surface/volume adaptively, see here.

As a starting point a would "duplicate" NURBSSurface.js and NURBSVolume.js to THBSplineSurface.js and THBSplineVolume.js thereby removing the weights and adding a function refine(...) where one can specify which regions should be refined. Secondly, I would have to add evaluation functions in NURBSUtils.js. Would that be of interest to three.js?

@Mugen87
Copy link
Collaborator

Mugen87 commented Jan 23, 2024

We are trying to keep the scope of the repository manageable so I would see a NURBS alternative maintained in a separate repository. That said, it is of course okay to add an external example (e.g. webgl_geometry_thb) that uses THB modules to showcase their usage. We do this for other third-party components as well like BVH, CSG or the IFC loader. Check out the examples here and how they include external libs in their import map:

https://threejs.org/examples/?q=external

@mmoelle1
Copy link
Contributor Author

mmoelle1 commented Jan 23, 2024 via email

@Mugen87
Copy link
Collaborator

Mugen87 commented Jan 23, 2024

I was more thinking of implementing the THB core functionality in three.js (two single JS files for surfaces and volumes).

It really depends on how complex the THB core functionality is. The number of files is not that much of a matter.

If it is comparable to the compact NURBSVolume class, it would be probably okay to add the code here. Otherwise using an external repository is the better choice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
2 participants