美文网首页
相连的系统I:绳子

相连的系统I:绳子

作者: 大龙10 | 来源:发表于2022-06-20 06:43 被阅读0次

    书名:代码本色:用编程模拟自然系统
    作者:Daniel Shiffman
    译者:周晗彬
    ISBN:978-7-115-36947-5
    目录

    5.18 相连的系统I:绳子

    1、模拟柔软物体

    • 在上例中,两个粒子对象通过一根弹簧相连。
    • toxiclibs物理库尤其适用于模拟柔软物体,
    • 比如可以用连接成一条线的粒子模拟绳子,
    • 可以用连接在一起的粒子网格模拟毯子。
    • 下面这个可爱的卡通模型也可以用相连的粒子进行模拟,这些粒子都通过弹簧相连。


      图5-14

    2、模拟一个“柔软的钟摆”模型

    • 下面我们要模拟一个“柔软的钟摆”模型——将摆球挂在绳子的底端,这里的摆臂不再是第3章里使用的刚性摆臂,而是图5-14所示的“绳子”。

    1)首先,我们需要一个粒子列表

    (使用上例的Particle类)

    ArrayList<Particle> particles = new ArrayList<Particle>();
    
    • 假如我们需要20个粒子,它们之间的间隔是10个像素。


      图5-15
    float len = 10;
    float numParticles = 20;
    
    • 我们可以将下标i从0递增到20,将每个粒子的y坐标设置成i * 10,这样一来,第1个粒子位于坐标(0,10),第2个粒子位于(0,20),第3个粒子位于(0,30)……
    for (int i=0; i < numPoints; i++) {
        Particle particle=new Particle(i*len, 10);  沿着x轴摆放粒子
        physics.addParticle(particle);   将粒子加入列表
        particles.add(particle);   将粒子加入物理世界
    }
    
    • 除了将粒子对象加入toxiclibs的物理世界,我们还将它放入自己的列表中。尽管这有些多余,但后面可能会有很多条绳子,到时候我们可以方便地获知粒子被连在哪一条绳子上。

    • 下面要做一件有趣的事:将所有的粒子连接在一起。粒子1和粒子0相连,粒子2和粒子1相连,粒子3和粒子2相连……


      图5-16
    • 也就是:粒子i和粒子i - 1相连(除去i等于0的情况)。

    if (i != 0) {
          Particle previous = particles.get(i-1);  首先,我们需要前一个粒子的引用
          VerletSpring2D spring = new VerletSpring2D(particle,previous,len,strength);
         之后,我们需要在两个粒子之间创建弹簧连接,并指定弹簧的静止长度和强度(都是浮点数)
          physics.addSpring(spring);  不要忘记将弹簧加入物理世界
      }
    
    • 如果我们想让绳子挂在某个定点上,该怎么做?可以将其中一个粒子锁定——比如第一个粒子、最后一个粒子或者最中间的粒子等。以下代码的作用就是将第一个粒子的位置锁定。
    Particle head=particles.get(0);
    head.lock();
    
    • 如果想要绘制绳子上的所有粒子,我们可以从ArrayList获取所有的粒子位置,再调用beginShape()函数、endShape()函数和vertex()函数绘制它们。

    3、示例

    示例代码5-11 柔软的钟摆

    import toxi.physics2d.*;
    import toxi.physics2d.behaviors.*;
    import toxi.geom.*;
    
    // Reference to physics "world" (2D)
    VerletPhysics2D physics;
    
    // Our "Chain" object
    Chain chain;
    
    void setup() {
      size(640, 360);
      // Initialize the physics world
      physics=new VerletPhysics2D();
      physics.addBehavior(new GravityBehavior(new Vec2D(0, 0.1)));
      physics.setWorldBounds(new Rect(0, 0, width, height));
    
      // Initialize the chain
      chain = new Chain(180, 20, 16, 0.2);
    }
    
    void draw() {
      background(255);
    
      // Update physics
      physics.update();
      // Update chain's tail according to mouse position 
      chain.updateTail(mouseX, mouseY);
      // Display chain
      chain.display();
    }
    
    void mousePressed() {
      // Check to see if we're grabbing the chain
      chain.contains(mouseX, mouseY);
    }
    
    void mouseReleased() {
      // Release the chain
      chain.release();
    }
    

    Chain.pde

    class Chain {
    
      // Chain properties
      float totalLength;  // How long
      int numPoints;      // How many points
      float strength;     // Strength of springs
      float radius;       // Radius of ball at tail
      
      // This list is redundant since we can ask for physics.particles, but in case we have many of these
      // it's a convenient to keep track of our own list
      ArrayList<Particle> particles;
    
      // Let's keep an extra reference to the tail particle
      // This is just the last particle in the ArrayList
      Particle tail;
    
      // Some variables for mouse dragging
      PVector offset = new PVector();
      boolean dragged = false;
    
      // Chain constructor
      Chain(float l, int n, float r, float s) {
        particles = new ArrayList<Particle>();
    
        totalLength = l;
        numPoints = n;
        radius = r;
        strength = s;
    
        float len = totalLength / numPoints;
    
        // Here is the real work, go through and add particles to the chain itself
        for(int i=0; i < numPoints; i++) {
          // Make a new particle with an initial starting position
          Particle particle=new Particle(width/2,i*len);
    
          // Redundancy, we put the particles both in physics and in our own ArrayList
          physics.addParticle(particle);
          particles.add(particle);
    
          // Connect the particles with a Spring (except for the head)
          if (i != 0) {
            Particle previous = particles.get(i-1);
            VerletSpring2D spring = new VerletSpring2D(particle,previous,len,strength);
            // Add the spring to the physics world
            physics.addSpring(spring);
          }
        }
    
        // Keep the top fixed
        Particle head=particles.get(0);
        head.lock();
    
        // Store reference to the tail
        tail = particles.get(numPoints-1);
        tail.radius = radius;
      }
    
      // Check if a point is within the ball at the end of the chain
      // If so, set dragged = true;
      void contains(int x, int y) {
        float d = dist(x,y,tail.x,tail.y);
        if (d < radius) {
          offset.x = tail.x - x;
          offset.y = tail.y - y;
          tail.lock();
          dragged = true;
        }
      }
    
      // Release the ball
      void release() {
        tail.unlock();
        dragged = false;
      }
    
      // Update tail position if being dragged
      void updateTail(int x, int y) {
        if (dragged) {
          tail.set(x+offset.x,y+offset.y);
        }
      }
    
      // Draw the chain
      void display() {
        // Draw line connecting all points
        beginShape();
        stroke(0);
        strokeWeight(2);
        noFill();
        for (Particle p : particles) {
          vertex(p.x,p.y);
        }
        endShape();
        tail.display();
      }
    }
    

    Particle.pde

    class Particle extends VerletParticle2D {
      
      float radius = 4;  // Adding a radius for each particle
      
      Particle(float x, float y) {
        super(x,y);
      }
    
      // All we're doing really is adding a display() function to a VerletParticle
      void display() {
        fill(127);
        stroke(0);
        strokeWeight(2);
        ellipse(x,y,radius*2,radius*2);
      }
    }
    

    4、运行结果

    相关文章

      网友评论

          本文标题:相连的系统I:绳子

          本文链接:https://www.haomeiwen.com/subject/vdsbmrtx.html