在Three.js布料的针脚位置

时间:2018-03-10 01:03:26

标签: javascript three.js

有人可以帮忙!我正在模拟一个贴在他们四角上的布料。我试图用10x10阵列重新定位布料的4针0,10,88,98。我希望能够将每个Pin放在x,y,z的不同位置。 对于这个模拟我使用Three.js和Cloth.js。 与此示例类似的东西: [https://threejs.org/examples/#webgl_animation_cloth][1]

这是我的代码,也是我正在使用的Cloth代码。

var pinsFormation = [];
pinsFormation.push( pins );
pins = [ 0, 10, 88, 98 ];
var container, stats;
var camera, scene, renderer, clothGeometry, object;

init();
animate();
        function init() {
            container = document.createElement( 'div' );
            document.body.appendChild( container );
            scene = new THREE.Scene();
            scene.background = new THREE.Color( 0xFFFFFF );

camera = new THREE.PerspectiveCamera( 30, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( 1000, 50, 1000 );

// cloth
var material_wire = new THREE.MeshBasicMaterial( { color : 0x000000, side: THREE.DoubleSide, wireframe: true } );
clothGeometry = new THREE.ParametricGeometry( clothFunction, cloth.w, cloth.h );

object = new THREE.Mesh( clothGeometry, material_wire );  // clothMaterial
object.position.set( 0, 0, 0 );
scene.add( object );

            // renderer
            renderer = new THREE.WebGLRenderer( { antialias: true } );
            renderer.setPixelRatio( window.devicePixelRatio );
            renderer.setSize( window.innerWidth, window.innerHeight );
            container.appendChild( renderer.domElement );
            var controls = new THREE.OrbitControls( camera, renderer.domElement );
            controls.maxPolarAngle = Math.PI * 1.5; 
            window.addEventListener( 'resize', onWindowResize, false );
        }

        function onWindowResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize( window.innerWidth, window.innerHeight );
        }
        function animate() {
            requestAnimationFrame( animate );
            var time = Date.now();
            var windStrength = Math.cos( time / 7000 ) * 20 + 40;
            windForce.set( Math.sin( time / 2000 ), Math.cos( time / 3000 ), Math.sin( time / 1000 ) )
            windForce.normalize()
            windForce.multiplyScalar( windStrength );
            simulate( time );
            render();   
        }
        function render() {
            var p = cloth.particles;
            for ( var i = 0, il = p.length; i < il; i ++ ) {
                clothGeometry.vertices[ i ].copy( p[ i ].position );
            }
            clothGeometry.verticesNeedUpdate = true;
            clothGeometry.computeFaceNormals();
            clothGeometry.computeVertexNormals();
            renderer.render( scene, camera );
        }

// cloth.js
var DAMPING = 0.03;
var DRAG = 1 - DAMPING;
var MASS = 0.1;
var restDistance = 25;
var xSegs = 10;
var ySegs = 10;
var clothFunction = plane( restDistance * xSegs, restDistance * ySegs );
var cloth = new Cloth( xSegs, ySegs );
var GRAVITY = 981 * 1.4;
var gravity = new THREE.Vector3( 0, - GRAVITY, 0 ).multiplyScalar( MASS );
var TIMESTEP = 18 / 1000;
var TIMESTEP_SQ = TIMESTEP * TIMESTEP;

    var pins = [];
    var wind = true;
    var windStrength = 2;
    var windForce = new THREE.Vector3( 0, 0, 0 ); 
    var tmpForce = new THREE.Vector3();
    var lastTime;

function plane( width, height ) {
    return function( u, v ) { 
        var x = ( u - 0.5 ) * width;
        var y = ( v - 0.1 ) * height; 
        var z = 0;
        return new THREE.Vector3( x, y, z );
    };
}
function Particle( x, y, z, mass ) {
    this.position = clothFunction( x, y ); // position
    this.previous = clothFunction( x, y ); // previous
    this.original = clothFunction( x, y );
    this.a = new THREE.Vector3( 0, 0, 0 ); // acceleration
    this.mass = mass;
    this.invMass = 1 / mass;
    this.tmp = new THREE.Vector3();
    this.tmp2 = new THREE.Vector3();
}

// Force -> Acceleration
Particle.prototype.addForce = function( force ) {
    this.a.add(
        this.tmp2.copy( force ).multiplyScalar( this.invMass )
    );
};

// Performs Verlet integration
Particle.prototype.integrate = function( timesq ) {
    var newPos = this.tmp.subVectors( this.position, this.previous );
    newPos.multiplyScalar( DRAG ).add( this.position );
    newPos.add( this.a.multiplyScalar( timesq ) );
    this.tmp = this.previous;
    this.previous = this.position;
    this.position = newPos;
    this.a.set( 0, 0, 0 );
};

var diff = new THREE.Vector3();
function satisfyConstraints( p1, p2, distance ) {
    diff.subVectors( p2.position, p1.position );
    var currentDist = diff.length();
    if ( currentDist === 0 ) return;
    var correction = diff.multiplyScalar( 1 - distance / currentDist );
    var correctionHalf = correction.multiplyScalar( 0.5 );
    p1.position.add( correctionHalf );
    p2.position.sub( correctionHalf );
}

function Cloth( w, h ) {
    w = w || 20;
    h = h || 20;
    this.w = w;
    this.h = h;
    var particles = [];
    var constraints = [];
    var u, v;
    // Create particles
    for ( v = 0; v <= h; v ++ ) {
        for ( u = 0; u <= w; u ++ ) {
            particles.push(
                new Particle( u / w, v / h, 0, MASS )
            );
        }
    }

// Structural
for ( v = 0; v < h; v ++ ) {
    for ( u = 0; u < w; u ++ ) {
        constraints.push( [
            particles[ index( u, v ) ],
            particles[ index( u, v + 1 ) ],
            restDistance
        ] );
        constraints.push( [
            particles[ index( u, v ) ],
            particles[ index( u + 1, v ) ],
            restDistance
        ] );
    }
}

for ( u = w, v = 0; v < h; v ++ ) {
    constraints.push( [
        particles[ index( u, v ) ],
        particles[ index( u, v + 1 ) ],
        restDistance

    ] );
}

for ( v = h, u = 0; u < w; u ++ ) {
    constraints.push( [
        particles[ index( u, v ) ],
        particles[ index( u + 1, v ) ],
        restDistance
    ] );
}
this.particles = particles;
this.constraints = constraints;
function index( u, v ) {
    return u + v * ( w + 1 );
}
this.index = index;
}

function simulate( time ) {
if ( ! lastTime ) {
lastTime = time;
return;
}

var i, il, particles, particle, pt, constraints, constraint;

// Aerodynamics forces
if ( wind ) {
    var face, faces = clothGeometry.faces, normal;
    particles = cloth.particles;
    for ( i = 0, il = faces.length; i < il; i ++ ) {
        face = faces[ i ];
        normal = face.normal;
        tmpForce.copy( normal ).normalize().multiplyScalar( normal.dot( windForce ) );
            particles[ face.a ].addForce( tmpForce );
            particles[ face.b ].addForce( tmpForce );
            particles[ face.c ].addForce( tmpForce );
        }
    }

for ( particles = cloth.particles, i = 0, il = particles.length; i < il; i ++ ) {
    particle = particles[ i ];
    particle.addForce( gravity );
    particle.integrate( TIMESTEP_SQ );
}

// Start Constraints
constraints = cloth.constraints;
il = constraints.length;
for ( i = 0; i < il; i ++ ) {
    constraint = constraints[ i ];
    satisfyConstraints( constraint[ 0 ], constraint[ 1 ], constraint[ 2 ] );
}

// Pin Constraints
for ( i = 0, il = pins.length; i < il; i ++ ) {
    var xy = pins[ i ];
    var p = particles[ xy ];
    p.position.copy( particles.original );
    p.previous.copy( particles.original );
}
}

1 个答案:

答案 0 :(得分:1)

&#34; pin&#34;只是其中一个顶点的索引..所以你要做的就是识别与你想要固定的点相对应的顶点..你可以在用户点击网格时从光线投射中得到它,或者从分析上看它。