Mesh editing: Vertices

0

Today has made, perhaps, the most significant functional for me. I was very interested in making the ability to edit the mesh of the object. So far, only moving vertices one at a time has been implemented. It took me 2 days to implement, and even more to ponder and theoretical preparation.

Editing is implemented for BufferGeometry.

First, I place small spheres to the vertices positions:

addPoints(){

        let points = getPoints( this.mesh );
        let vertexes = getVertexes( points );

        addSpheresToVertexes( this.mesh, vertexes );

    }

Since the coordinates of the vertices are stored in a buffer, which is an array of values in increments of 3: [x1, y1, z1, x2, y2, z2 … xn, yn, zn], we need to get the coordinates of the points in the form of vectors

function getPoints( mesh ) {

    let pointsArray = mesh.geometry.attributes.position.array;
    let itemSize = mesh.geometry.attributes.position.itemSize;

    let points = [];

    for (let i = 0; i < pointsArray.length; i += itemSize ) {

        points.push( new Vector3( pointsArray[i], pointsArray[i+1], pointsArray[i+2]));

    }

    return points;

}

But the points are repeated. For example, for a cube (8 vertices) – 24 points, 3 points per vertex (one point for one face)

We get an array of vertex coordinates:

function getVertexes( points ) {

    let vertexes = [];

    points.forEach( ( indexPoints ) => {

        let equal = false;

        vertexes.forEach( ( indexVertex ) => {
            
            if (indexPoints.equals( indexVertex) ){

                equal = true;
                return;

            } 

        })

        if ( !equal ) {

            vertexes.push( indexPoints );

        }

    })

    return vertexes;

}

At each vertex we put a sphere

function addSpheresToVertexes( mesh, vertexes ){

    let ta_Scene = new TA_Scene();
    let sphereGeometry = new SphereBufferGeometry( 0.3, 4, 4 );
    
    ta_Scene.tempSelectableObjects = ta_Scene.tempSelectableObjects.concat( ta_Scene.selectableObjects );

    ta_Scene.selectableObjects = [];

    let group = new Group();
    group.name = 'shperesForMeshEdit';

    vertexes.map( (item, index) => {
        let sphere = new Mesh( sphereGeometry, new MeshBasicMaterial( { color: new Color( 'red' ) } ) );
        sphere.name = 'editMeshHelper'
        sphere.userData.vertexNumer = `${index}` ;
        group.add( sphere );
        sphere.position.set( item.x, item.y, item.z);
        ta_Scene.selectableObjects.push( sphere );

    })

    mesh.add( group );

}

I did the editing of the geometry using the static method. I pass in it an object, the number of the vertex, which will change and its position

    static changeGeometry( object, vertexNumber, position ){

        let ta_Entities = new TA_Entities();
        let points = getPoints( object );
        let vertexes = getVertexes( points );
        let VertexesPointsIndexes = getVertexesPointsIndexes( points, vertexes);

        ta_Entities.removeWireframeAndBoundingBox(object );

        vertexes[ +vertexNumber ] = position;

        let newPoints = vertexesChangePoints ( vertexes, points, VertexesPointsIndexes);
        

        pointsChangeAttributesPosition( object, newPoints );
        object.geometry.attributes.position.needsUpdate = true;
    
        object.updateMatrix();
        // object.add( ta_Entities.createBoundingBox( object ) );
        object.add( ta_Entities.createWireframe( object ) );

    }

Now we need to do the reverse procedure.

We find in what positions of the points array the coordinates of the vertices are contained

function getVertexesPointsIndexes( points, vertexes){

    let indexesArray = [];
    vertexes.map ( (itemVertex ) => {
        let indexes = [];
        points.forEach( (itemPoints, index) => {
            if( itemPoints.equals( itemVertex ) )
            indexes.push( index );
        })
        indexesArray.push( indexes );

    })

    return indexesArray;

}

Change the value of the vertex position

vertexes[ +vertexNumber ] = position;

and change the points array

function vertexesChangePoints ( vertexes, points, VertexesPointsIndexes) {

    // let newPoints = points;
    vertexes.map( ( itemVertex, index ) => {

        let arrayIndexes = VertexesPointsIndexes[ index ];

        arrayIndexes.map( ( item ) => points[ item ] = itemVertex);

    })

    points[0] = vertexes[0];

    return points;

}

Which in turn changes the values in the object buffer

function pointsChangeAttributesPosition( mesh, points ) {
    
    let positions = [];

    points.map( (item) => {
        positions.push( item.x);
        positions.push( item.y);
        positions.push( item.z);

    } )

    let arrayAttr = mesh.geometry.attributes.position.array;

    arrayAttr.map( (item, index) => { 

        mesh.geometry.attributes.position.array[index] = positions[index]

    })

}

Change occurs on an event

   this.transformControls.addEventListener( 'objectChange', function( event ) {

 if( event.target.mode === 'translate' ){

                if ( scope.mode.action === 'meshEdit' ){

                    let vertexNumber = event.target.object.userData.vertexNumer;
                    let position = event.target.object.position;
                    let object = event.target.object.parent.parent;

                    MeshEdit.changeGeometry( object, +vertexNumber, position );

                }

0