首页 > 解决方案 > 有没有办法从three.js中的函数参数获取位置(xyz)?

问题描述

我试图根据 three.js 文档中的布料示例构建一个标志,但在定义标志的约束时遇到了麻烦。
示例链接:
https
://threejs.org/examples/#webgl_animation_cloth 示例 源代码:https ://github.com/mrdoob/three.js/blob/master/examples/webgl_animation_cloth.html

因为代码有大约 300 行,所以我已经尽我最大的努力注释每个代码块。

在我的解释中, function SatisfyConstraints在两点之间进行减法以获得微分向量。然后它计算长度并从中得出修正。
代码末尾的“模拟”函数 SatisfyConstraints用于调节旗帜的飘扬方式。

     var container, renderer, scene, camera, controls; 
     var near, far; 

   var params = {
   enableWind: true, 
   showBall: false 
    }

        var DAMPING = 0.03; 
        var MASS = 0.15; 
        var DRAG = 1 - DAMPING; 
        var DistanceUntilRest = 25;
        var GRAVITY = 981 * 1.4;
        var gravityVector = new THREE.Vector3( 0, - GRAVITY, 0 ).multiplyScalar( MASS );  // F = mg 
        var ForceVector = new THREE.Vector3();  
        var windForce = new THREE.Vector3( 0, 0, 0 ); 

        var TIMESTEP = 18 / 1000;
        var TIMESTEP_SQ = TIMESTEP * TIMESTEP;

        var xSegs = 10, ySegs = 10; 

        var clothFunction = planeEquation( DistanceUntilRest * xSegs,  DistanceUntilRest * ySegs ); 
        var cloth = new Cloth(xSegs, ySegs); 

    function planeEquation (width, height) { 
        return function (a, b, target) {
            var x = (a - 0.5) * width; 
            var y = (b + 0.5) * height; 
            var z = 0;  // idk why z has to be 0 
            target.set( x, y, z); 
        }
    }


    function Particles (x, y, z, mass) {
        this.position = new THREE.Vector3(); 
        this.previous = new THREE.Vector3(); 
        this.original = new THREE.Vector3();  
        this.acceleration = new THREE.Vector3( 0 , 0 , 0);  
        this.mass = mass;  
        this.invMass = 1 / mass; 
        this.FVector = new THREE.Vector3(); 
        this.tmp = new THREE.Vector3(); 


        // initializing clothFunction so planeEquation can set the target 

        clothFunction(x, y, this.position);
        clothFunction(x, y, this.previous);
        clothFunction(x, y, this.original); 


    }
  // converting force into acceleration 
    Particles.prototype.addForce = function (force) {
            this.acceleration.add( this.FVector.add(force).multiplyScalar(this.invMass) )
    };

        // after each time sequence the new position adds itself by the amount of drag and acceleration 

     Particles.prototype.integrate = function (timeSequence) {
            var newPos = this.tmp.subVectors(this.position, this.previous);
            newPos.multiplyScalar(DRAG).add(this.position); 
            newPos.add( this.acceleration.multiplyScalar( timeSequence ) );

            // passes tmp down to this.previous then assumes this.position as the new position 

            this.tmp = this.previous; 
            this.previous = this.position; 
            this.position = newPos; 

            // resetting acceleration 

            this.acceleration.set(0, 0, 0); 
    }; 

    var diff = new THREE.Vector3(); 

    function SatisfyConstraints (point, next_point, distance) { 
        diff.subVectors(next_point.position, point.position); 
        var currentDist = diff.length();  
        if (currentDist === 0) return; 

        var correction = diff.multiplyScalar(1 - distance / currentDist);
        var correctionHalf = correction.multiplyScalar(0.5);    
        point.position.add( correctionHalf );
        next_point.position.sub( correctionHalf );
    }
    function Cloth(width, height) { 
        this.width = width || 10; 
        this.height = height || 10; 

        var particles = [], constraints = [];  
        var i, j, u, v;   

        for (i = 0; i <= height; i++ ) {
            for (j = 0; j <= width; j++) {
                particles.push( new Particles( i / width, j / height, 0, MASS) )
            }
        }

        // Providing structure for cloth - similar to drawing 
        for (i = 0; i <= height; i++ ) {
            for (j = 0; j <= width; j++) { 
                constraints.push([ 
                    particles[index(i, j)],
                    particles[index(i, j + 1)], 
                     DistanceUntilRest 
                ]);

                constraints.push([ 
                    particles[index(i, j)],
                    particles[index(i + 1, j)], 
                     DistanceUntilRest 
                ])
            }
        }

        for ( u = width, v = 0; v < height; v ++ ) {
                    constraints.push( [
                        particles[ index( u, v ) ],
                        particles[ index( u, v + 1 ) ],
                        DistanceUntilRest
                    ] );
                }

        for ( v = height, u = 0; u < width ; u ++ ) {
                    constraints.push( [
                        particles[ index( u, v ) ],
                        particles[ index( u + 1, v ) ],
                        DistanceUntilRest
                    ] );
                }



            this.particles = particles;
            this.constraints = constraints;

        function index( u, v ) {
                    return u + v * ( width + 1 );
            }
        this.index = index;
    } 

function simulate( time ) {
                if ( ! lastTime ) {
                    lastTime = time;
                    return;
                }
                var i, j, il, particles, particle, constraints, constraint;
                // Aerodynamics forces
                if ( params.enableWind ) {
                    var indx;
                    var normal = new THREE.Vector3();
                    var indices = clothGeometry.index;
                    var normals = clothGeometry.attributes.normal;
                    particles = cloth.particles;
                    for ( i = 0, il = indices.count; i < il; i += 3 ) {
                        for ( j = 0; j < 3; j ++ ) {
                            indx = indices.getX( i + j );
                            normal.fromBufferAttribute( normals, indx );
                            tmpForce.copy( normal ).normalize().multiplyScalar( normal.dot( windForce ) );
                            particles[ indx ].addForce( tmpForce );
                        }
                    }
                }
                for ( particles = cloth.particles, i = 0, il = particles.length; i < il; i ++ ) {
                    particle = particles[ i ];
                    particle.addForce( gravityVector );
                    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 ] );
                }

                var pos; 

                // Ball Constraints
                ballPosition.z = - Math.sin( Date.now() / 600 ) * 90; //+ 40;
                ballPosition.x = Math.cos( Date.now() / 400 ) * 70;
                if ( params.showBall ) {
                    sphere.visible = true;
                    for ( particles = cloth.particles, i = 0, il = particles.length; i < il; i ++ ) {
                        particle = particles[ i ];
                        pos = particle.position;
                        diff.subVectors( pos, ballPosition );
                        if ( diff.length() < ballSize ) {
                            // collided
                            diff.normalize().multiplyScalar( ballSize );
                            pos.copy( ballPosition ).add( diff );
                        }
                    }
                } else {
                    sphere.visible = false;
                }
                // 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;
                        }
                    }
    }

我还尝试position.copy(point), position.copy(next_point)在 SatisfyConstraints 中使用来复制坐标并将传递的参数粘贴到新变量中,但它不起作用。

function SatisfyConstraints (point, next_point, distance) {  
        var pointPos, next_pointPos; 
        pointPos.position.copy(point); 
        next_pointPos.position.copy(next_point);  
        diff.subVectors(pointPos, next_pointPos); 
        ... 
} 

我希望SatisfyConstraints能像往常一样工作,但我收到了如下错误消息:

未捕获的类型错误:在动画 (simulation3D.html:419) 的模拟 (simulation3D.html:212)处 无法读取
SatisfyConstraints (simulation3D.html:102) 处未定义的属性“位置”


标签: javascriptthree.js

解决方案


使用chrome开发工具调试)

function SatisfyConstraints (point, next_point, distance) {  
    var pointPos, next_pointPos; 
    pointPos.position.copy(point); // <-using of undefined (not-initialized) pointPos
    next_pointPos.position.copy(next_point);  
    diff.subVectors(pointPos, next_pointPos); 
    ...  

我猜 pointPos 应该是 THREE.Vector3 类的一个实例。


推荐阅读