Is there any way to get the position ( x, y, z) from a function parameter?

was trying to build a flag based on the cloth example in the three.js documentation but I have trouble in defining the constraints for the flag.
Link to the example:
https://threejs.org/examples/#webgl_animation_cloth
Source code of the example: https://github.com/mrdoob/three.js/blob/e0a31ea77c0242ae29ef6e951fa588216e1d247f/examples/webgl_animation_cloth.html

I had already tried my best to comment every block of code since the code has ~300 lines.

In my interpretation, function SatisfyConstraints makes a subtraction between two points in order to get the differentiation vector . Then it calculates the length and derive corrections from it.
The “simulate” function at the end of the code uses SatisfyConstraints to regulate how the flag should be flown.

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);  
      
     Particles.prototype.addForce = function (force) {
            this.acceleration.add( this.FVector.copy(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;
                        }
                    }
    }

I also attempted to use position.copy(point), position.copy(next_point) in SatisfyConstraints) to copy the coordinates and paste the passed parameters into a new variable but it doesn’t work.

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); 
        ... 
} 

I’d expected SatisfyConstraints to function as usual but instead I received the error message as follows:

Uncaught TypeError: Cannot read property ‘position’ of undefined
at SatisfyConstraints (simulation3D.html:102)
at simulate (simulation3D.html:212)
at animate (simulation3D.html:419)

That is because pointPos is undefined. You have only declared it with var pointPos.

Even if I define pointPos as a new THREE.Vector3() it still won’t work.

Vector3 has no position property. Object3D has, though. I guess you mean:

var pointPos = new THREE.Vector3();
pointPos.copy(point);

if point is a Vector3, or

var pointPos = new THREE.Vector3();
pointPos.copy(point.position);

if point is an Object3D.

Yeah exactly.
I never thought about Object3D at all. :slight_smile: .Thanks a lot

1 Like