Morphing between two geometries

For this reason I have created a suitable geometry. For this I use the scheme from my Addon. Produces almost infinite many time-varying geometries with functions .

It is symmetrical and therefore suitable.

See THREEf geometries r136

With a little elementary geometry, the transformation from cube to sphere can be easily achieved.

The uv values are still missing, will be supplied later.


UPDATE:

The ready solution there Morph box sphere geometry (+shader)



<!DOCTYPE html>
<!-- https://discourse.threejs.org/t/morphing-between-two-geometries/31911 -->
<head>
  <title> MorphBoxSphere </title>
  <meta charset="utf-8" />
    <meta charset="utf-8" />
    <style>
    body {
        margin: 0; 
        overflow: hidden;
    }
    </style>
</head>
<body> </body>

<script src="../js/three.min.134.js"></script>
<script src="../js/OrbitControls.134.js"></script>

<script>

// @author hofk

const scene = new THREE.Scene();

const camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.set( 0,  0, 10);

const renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xdedede, 1 );
document.body.appendChild( renderer.domElement );

const controls = new THREE.OrbitControls( camera, renderer.domElement );

const g = new THREE.BufferGeometry( );

const r = 3; // radius sphere === space cube diagonal 
// const sd = r * 1 / Math.sqrt( 2 ); // 1/2 square diagonal
const ss = r * 1 / Math.sqrt( 3 ); // 1/2 square side

const cs = 8; // count of segments per side

const axesHelper = new THREE.AxesHelper( r );
scene.add( axesHelper );

const css = cs + 1;
const hvc = css + cs ;   // height vertex count
const vertexCount = css * css + cs * cs;	
const faceCount = cs * cs * 4;

let a0, b0, c0, a1, b1, c1, le;

const indices = new Uint32Array( faceCount * 3 * 6 );
const positions = new Float32Array( vertexCount * 3 * 6 );   
//const uvs = new Float32Array( vertexCount * 2 * 6 ); // uvs to vertices	

g.setIndex( new THREE.BufferAttribute( indices, 1 ) );	
g.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ).setUsage( THREE.DynamicDrawUsage) );
//g.setAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );

const cube = new Float32Array( vertexCount * 3 * 6 ); // basis positions plane,cube
const diff = new Float32Array( vertexCount * 3 * 6 ); // difference positions cube sphere

//face indices

let idx = 0;
let offs = 0;

for ( let k = 0; k < 6; k ++ ) {

    for ( let j = 0; j < cs; j ++ ) {
    
        for ( let i = 0; i < cs; i ++ ) {
        
            // 4 faces / segment
            a  = offs + hvc * j + css + i;
            
            b1 = offs + hvc * j + i;				// bottom
            c1 = offs + hvc * ( j + 1 ) + i;
            
            b2 = offs + hvc * j + 1 + i;			// left
            c2 = offs + hvc * j + i;
            
            b3 = offs + hvc * ( j + 1 ) + i;		// right
            c3 = offs + hvc * ( j + 1 ) + 1 + i;
            
            b4 = offs + hvc * ( j + 1 ) + 1 + i;	// top
            c4 = offs + hvc * j + 1 + i;
            
            indices[ idx] = a;		    // bottom
            indices[ idx + 1 ] = b1;
            indices[ idx + 2 ] = c1; 
            
            indices[ idx + 3 ] =  a;    // left
            indices[ idx + 4 ] =  b2,
            indices[ idx + 5 ] =  c2; 
            
            indices[ idx + 6 ] = a;	    // right
            indices[ idx + 7 ] = b3;
            indices[ idx + 8 ] = c3; 
            
            indices[ idx + 9 ] =  a;    // top
            indices[ idx + 10 ] =  b4,
            indices[ idx + 11 ] =  c4;
            
            idx += 12;
            
        }
    
    }
    
    offs += hvc * cs + css; // + vertex count one side
    
}

const v = t => 0.5 * ( 1 + Math.sin( t ) );

idx = 0; // reset

           // ia, ib, ic, sign 
makePositions( 0,  1,  2,  1 );
makePositions( 0,  1,  2, -1 );
makePositions( 1,  2,  0,  1 );
makePositions( 1,  2,  0, -1 );
makePositions( 2,  0,  1,  1 );
makePositions( 2,  0,  1, -1 );

function makePositions( ia, ib, ic, sign ) {
    
    for ( let j = 0; j < css; j ++ ) {
    
        for ( let i = 0; i < css; i ++ ) {
            
            a0 = -ss + 2 * ss * j / cs;
            b0 = -ss + 2 * ss * i / cs;
            c0 = sign * ss;
            
            cube[ idx + ia ] = a0;
            cube[ idx + ib ] = b0;
            cube[ idx + ic ] = c0;
            
            le = Math.sqrt( a0 * a0 + b0 * b0 + c0 * c0 );       
            
            a1 = r * a0 / le;
            b1 = r * b0 / le;
            c1 = r * c0 / le;
            
            diff[ idx + ia ] = a1 - a0;
            diff[ idx + ib ] = b1 - b0;
            diff[ idx + ic ] = c1 - c0;
            
            positions[ idx + ia ] = a0; 
            positions[ idx + ib ] = b0;
            positions[ idx + ic ] = c0;        
            
            idx += 3;
            
        }
        
        if( j < cs ) {
            
            for ( let i = 0; i < cs; i ++ ) {
                    
                a0 = -ss + 2 * ss * ( j + 0.5 ) / cs;
                b0 = -ss + 2 * ss * ( i + 0.5 ) / cs;
                c0 = sign * ss;
                
                cube[ idx + ia ] = a0;
                cube[ idx + ib ] = b0;
                cube[ idx + ic ] = c0;
                
                le = Math.sqrt( a0 * a0 + b0 * b0 + c0 * c0 );
                
                a1 = r * a0 / le;
                b1 = r * b0 / le;
                c1 = r * c0 / le;
                
                diff[ idx + ia ] = a1 - a0;
                diff[ idx + ib ] = b1 - b0;
                diff[ idx + ic ] = c1 - c0;
                
                positions[ idx + ia ] = a0;
                positions[ idx + ib ] = b0;
                positions[ idx + ic ] = c0;
                
                idx += 3;
                
            }
            
        }
        
    }
    
}
//console.log( 'cube ', cube) /////////////////////////////////////////////////////////////////////////
//console.log( 'diff ', diff) /////////////////////////////////////////////////////////////////////////
//console.log( positions )///////////////////////////////////////////////////////////////////////

const mat = new THREE.MeshBasicMaterial( { color: 0xff00ff, wireframe: true, side: THREE.DoubleSide  } );
const mesh = new THREE.Mesh( g, mat  );
scene.add( mesh )
 
const clock = new THREE.Clock( );
let t;

animate( );

function animate( ) {
    
    t = clock.getElapsedTime( );

    requestAnimationFrame( animate );
    morph( t );
    renderer.render( scene, camera );
    
}

function morph( t ) {

    idx = 0; // reset
              // ia, ib, ic 
    setPositions( 0,  1,  2 );
    setPositions( 0,  1,  2 );
    setPositions( 1,  2,  0 );
    setPositions( 1,  2,  0 );
    setPositions( 2,  0,  1 );
    setPositions( 2,  0,  1 );
    
    g.attributes.position.needsUpdate = true;// to change the positions of the vertices
    
    function setPositions( ia, ib, ic ) {
        
        for ( let j = 0; j < css; j ++ ) {
        
            for ( let i = 0; i < css; i ++ ) {
                
                positions[ idx + ia ] = cube[ idx + ia ] + v( t ) * diff[ idx + ia ]; 
                positions[ idx + ib ] = cube[ idx + ib ] + v( t ) * diff[ idx + ib ];
                positions[ idx + ic ] = cube[ idx + ic ] + v( t ) * diff[ idx + ic ];        
            
                idx += 3;
                
            }
        
            if( j < cs ) {
                
                for ( let i = 0; i < cs; i ++ ) {
                    
                    positions[ idx + ia ] = cube[ idx + ia ] + v( t ) * diff[ idx + ia ]; 
                    positions[ idx + ib ] = cube[ idx + ib ] + v( t ) * diff[ idx + ib ];
                    positions[ idx + ic ] = cube[ idx + ic ] + v( t ) * diff[ idx + ic ];        
                
                    idx += 3;
                
                }
            
            }
            
        }
        
    }
    
}

</script>    
</html>
1 Like