Моделирование ткани Y сегменты прекращают анимацию

Я пытаюсь узнать и понять, как работает Three.js. Я начал с моделирования ткани, но столкнулся с ошибкой. Кажется, установка ткани на ширину выше 25, заставляет сегменты начинать кластеризоваться.

Я устанавливаю ширину в файле Cloth.js, где var ySegs = 60;, в консоли я получаю предупреждение "THREE.WebGLRenderer: изображение не является степенью двойки (1800x2819). При изменении размера до 2048x2048", эти проблемы связаны? Был бы очень признателен, если бы кто-то мог помочь мне понять, что вызывает эту проблему здесь.

// Cloth.js
var DAMPING = 0.03;
var DRAG = 1 - DAMPING;
var MASS = 0.1;
var restDistance = 25;

var xSegs = 12;
var ySegs = 25;

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 ballPosition = new THREE.Vector3( 0, - 45, 0 );
var ballSize = 60; //40

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.5 ) * 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; // prevents division by 0
 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 || 10;
 h = h || 10;
 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 ] );

 }

 // Ball Constraints

 ballPosition.z = - Math.sin( Date.now() / 600 ) * 90 ; //+ 40;
 ballPosition.x = Math.cos( Date.now() / 400 ) * 70;

 if ( sphere.visible ) {

  for ( particles = cloth.particles, i = 0, il = particles.length; i < il; i ++ ) {

   particle = particles[ i ];
   var pos = particle.position;
   diff.subVectors( pos, ballPosition );
   if ( diff.length() < ballSize ) {

    // collided
    diff.normalize().multiplyScalar( ballSize );
    pos.copy( ballPosition ).add( diff );

   }

  }

 }


 // Floor Constraints

 for ( particles = cloth.particles, i = 0, il = particles.length; i < il; i ++ ) {

  particle = particles[ i ];
  pos = particle.position;
  if ( pos.y < - 250 ) {

   pos.y = - 250;

  }

 }

 // Pin Constraints

 for ( i = 0, il = pins.length; i < il; i ++ ) {

  var xy = pins[ i ];
  var p = particles[ xy ];
  p.position.copy( p.original );
  p.previous.copy( p.original );

 }
}

   /* Testing */
   var pinsFormation = [];
   var pins = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
   pinsFormation.push( pins );
   pins = pinsFormation[ 0 ];
   function togglePins() {
    pins = pinsFormation[ ~~ ( Math.random() * pinsFormation.length ) ];
   }

            var colours = [
                {bg: 'rgb(56, 255, 211)', flag:'assets/images/rectangle_3.png'},
                {bg: 'rgb(255, 190, 73)', flag:'assets/images/rectangle_1.png'},
                {bg: 'rgb(227, 195, 255)', flag:'assets/images/rectangle_2.png'}
            ];
            var colourChoice = colours[ ~~ ( Math.random() * colours.length ) ];

   if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
   var container, stats;
   var camera, scene, renderer;
   var clothGeometry;
   var sphere;
   var object;
   init();
   animate();
   function init() {
    container = document.createElement('div');
                container.setAttribute("id", "canvas-cnt");
    document.body.appendChild( container );
    // scene
    scene = new THREE.Scene();
    scene.background = new THREE.Color(colourChoice.bg);
    
    // camera
    camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
    camera.position.x = 0;
    camera.position.y = -300;
    camera.position.z = 1800;
    scene.add(camera);

    // lights
    var light, materials;
    scene.add( new THREE.AmbientLight( 0x666666 ) );
    light = new THREE.DirectionalLight( 0xdfebff, 1.75 );
    light.position.set( 50, 200, 100 );
    light.position.multiplyScalar( 1.3 );
    light.castShadow = true;
    light.shadow.mapSize.width = 1024;
    light.shadow.mapSize.height = 1024;
    var d = 300;
    light.shadow.camera.left = - d;
    light.shadow.camera.right = d;
    light.shadow.camera.top = d;
    light.shadow.camera.bottom = - d;
    light.shadow.camera.far = 1000;
    scene.add( light );

    // cloth material
    var loader = new THREE.TextureLoader();
    var clothTexture = loader.load(colourChoice.flag);
    clothTexture.wrapS = clothTexture.wrapT = THREE.RepeatWrapping;
    clothTexture.anisotropy = 16;
    var clothMaterial = new THREE.MeshPhongMaterial( {
     specular: 0x030303,
     map: clothTexture,
     side: THREE.DoubleSide,
     alphaTest: 0.5
    } );
    // cloth geometry
    clothGeometry = new THREE.ParametricGeometry( clothFunction, cloth.w, cloth.h );
    clothGeometry.dynamic = true;
                console.log(cloth.w, cloth.h);
    var uniforms = { texture:  { value: clothTexture } };
    var vertexShader = document.getElementById( 'vertexShaderDepth' ).textContent;
    var fragmentShader = document.getElementById( 'fragmentShaderDepth' ).textContent;
    // cloth mesh
    object = new THREE.Mesh( clothGeometry, clothMaterial );
    object.position.set( 0, 130, 0 );

                object.rotateZ( Math.PI / 2 );
    object.castShadow = true;
    scene.add( object );
    object.customDepthMaterial = new THREE.ShaderMaterial( {
     uniforms: uniforms,
     vertexShader: vertexShader,
     fragmentShader: fragmentShader,
     side: THREE.DoubleSide
    } );
    // sphere
    var ballGeo = new THREE.SphereGeometry( ballSize, 20, 20 );
    var ballMaterial = new THREE.MeshPhongMaterial( { color: 0xaaaaaa } );
    sphere = new THREE.Mesh( ballGeo, ballMaterial );
    sphere.castShadow = true;
    sphere.receiveShadow = true;
    scene.add( sphere );

    // renderer
    renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( window.innerWidth, window.innerHeight );
    renderer.shadowMap.renderSingleSided = false;
    container.appendChild( renderer.domElement );
    renderer.gammaInput = true;
    renderer.gammaOutput = true;
    renderer.shadowMap.enabled = true;
    // controls
    var controls = new THREE.OrbitControls( camera, renderer.domElement );
    controls.maxPolarAngle = Math.PI * 0.5;
    controls.minDistance = 1000;
    controls.maxDistance = 7500;
    // performance monitor
    stats = new Stats();
    container.appendChild( stats.dom );
    //
    window.addEventListener( 'resize', onWindowResize, false );
    sphere.visible = ! true;
   }
   //
   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 = 40;
    
    windForce.set( 1000, 1000, 4200 )
    windForce.normalize()
    windForce.multiplyScalar( windStrength );
    simulate( time );
    render();
    stats.update();
   }
   function render() {
    var p = cloth.particles;
    for ( var i = 0, il = p.length; i < il; i ++ ) {
     clothGeometry.vertices[ i ].copy( p[ i ].position );
    }
    clothGeometry.computeFaceNormals();
    clothGeometry.computeVertexNormals();
    clothGeometry.normalsNeedUpdate = true;
    clothGeometry.verticesNeedUpdate = true;
    
    camera.lookAt( scene.position );
    renderer.render( scene, camera );
   }
<script type="x-shader/x-fragment" id="fragmentShaderDepth">
    #include <packing>
    uniform sampler2D texture;
    varying vec2 vUV;
    void main() {
        vec4 pixel = texture2D( texture, vUV );
        if ( pixel.a < 0.5 ) discard;
        gl_FragData[ 0 ] = packDepthToRGBA( gl_FragCoord.z );
    }
</script>

<script type="x-shader/x-vertex" id="vertexShaderDepth">
    varying vec2 vUV;
    void main() {
        vUV = 0.75 * uv;
        vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
        gl_Position = projectionMatrix * mvPosition;
    }
</script>

0 ответов

Другие вопросы по тегам