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