首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用lerp函数(处理)更改位置

使用lerp函数(处理)更改位置
EN

Stack Overflow用户
提问于 2022-02-07 17:27:50
回答 2查看 221关注 0票数 0

+++编辑+++

我有一个由单个矩形组成的网格。现在,我想用Lerp函数将每个矩形移动到一个新位置(当前是MouseX,MouseY)。到目前为止,我只设法把电网作为一个整体-一个不必要的扭曲.这可能是由于PushMatrix();PopMatrix();?

我是否必须以完全不同的方式构建网格,才能使每个矩形都流向鼠标指针?或者lerp();只是做错了这个函数?

这就是我已经走了这么远:

代码语言:javascript
复制
float size;
float pixel;
float lx;
float ly;

void setup() {
  size(600, 600);
  pixel = 100;
  size = width/pixel;
  rectMode(CENTER);
}

void draw() {
  background(0);
  //DRAW THE GRID

  lx = 0;
  ly = 0;

  for (int y = 0; y < pixel; y++) {
    ly = lerp(ly, mouseY, 0.05);
    for (int x = 0; x < pixel; x++) {
      lx = lerp(lx, mouseX, 0.05);
      pushMatrix();
      translate(size/2, size/2);
      translate(x*size, y*size);
      rotate(radians(45));
      fill(255);
      noStroke();
      rect(lx, ly, size, size);
      popMatrix();
    }
  }
}

我建电网的方式能做到这一点吗?

EN

回答 2

Stack Overflow用户

发布于 2022-02-07 19:36:35

您的lerp函数用于计算两个位置之间的步骤,因此您需要转换的起始位置和结束位置,并且您将多次调用lerp来重新计算每个步骤。您可以将lerp看作是在增量步骤中将最后一个参数从0.0更改为1.0时,计算源和目标之间距离的百分比。

代码语言:javascript
复制
rectY=?;
rectX=?; // Replace the '?' marks with the left and top starting positions of your rectangle
for (int step=1; step<=20; step++) {
    lx = lerp(rectX, mouseX, 0.05 * step);
    ly = lerp(rectY, mouseY, 0.05 * step);
    ...
}
票数 1
EN

Stack Overflow用户

发布于 2022-02-15 01:39:29

你已经通过lerp()获得了宽松政策。

下面是一个使用单个网格元素的简化示例:

代码语言:javascript
复制
float easeAmount = 0.05;

float lx, ly;

void setup(){
  size(600, 600); 
}

void draw(){
  lx = lerp(lx, mouseX, easeAmount);
  ly = lerp(ly, mouseY, easeAmount);
  
  background(0);
  quad(lx, ly, 30);
}

void quad(float x, float y, float size){
  float halfSize = size * 0.5;
  quad(x            , y - halfSize, // top
       x + halfSize , y           , // right
       x            , y + halfSize, // bottom
       x - halfSize , y             // left
       );
}

手动放松非常类似:

代码语言:javascript
复制
float easeAmount = 0.05;

float lx, ly;

void setup(){
  size(600, 600); 
}

void draw(){
  lx += (mouseX - lx) * easeAmount;
  ly += (mouseY - ly) * easeAmount;;
  
  background(0);
  quad(lx, ly, 30);
}

void quad(float x, float y, float size){
  float halfSize = size * 0.5;
  quad(x            , y - halfSize, // top
       x + halfSize , y           , // right
       x            , y + halfSize, // bottom
       x - halfSize , y             // left
       );
}

上述草图的思想是简化为单个元素(并丢弃push/pop矩阵和旋转调用)。

您的方法的一个缺点是,对于所有网格元素,您都有一个单独的lx/ly协同项:可能更容易拥有独立的对:每个元素一个。

下面是一个使用2D数组为每个网格元素存储一对简化位置的示例:

代码语言:javascript
复制
float easeAmount = 0.05;

// rows and columns
int gridSize = 100;
int numElements = gridSize * gridSize;

float gridElementSize = 6;

float[][] positions = new float[numElements][2];

void setup(){
  size(600, 600); 
  
  // initialise grid positions
  int elementIndex = 0;
  for(int y = 0 ; y < gridSize; y++){
    for(int x = 0; x < gridSize; x++){
      // grid x position
      positions[elementIndex][0] = x * gridElementSize; 
      // grid y position
      positions[elementIndex][1] = y * gridElementSize; 
      // increment element counter
      elementIndex++;
    }
  }
}

void draw(){
  background(0);
  
  for(int elementIndex = 0; elementIndex < numElements; elementIndex++){
    positions[elementIndex][0]  = lerp(positions[elementIndex][0] , mouseX, easeAmount);
    positions[elementIndex][1]  = lerp(positions[elementIndex][1] , mouseY, easeAmount);
    
    // render updated quad
    quad(positions[elementIndex][0], positions[elementIndex][1], gridElementSize);
  }
  
}

void quad(float x, float y, float size){
  float halfSize = size * 0.5;
  quad(x            , y - halfSize, // top
       x + halfSize , y           , // right
       x            , y + halfSize, // bottom
       x - halfSize , y             // left
       );
}

注意,单个元素向鼠标移动,但是移动速度相同,似乎是作为一个组移动。

但是,您可以添加一些随机性来打破单调的运动:

代码语言:javascript
复制
float easeAmount = 0.05;

// rows and columns
int gridSize = 100;
int numElements = gridSize * gridSize;

float gridElementSize = 6;

float[][] positions = new float[gridSize * gridSize][2];

void setup(){
  size(600, 600); 
  noStroke();
  // initialise grid positions
  int elementIndex = 0;
  for(int y = 0 ; y < gridSize; y++){
    for(int x = 0; x < gridSize; x++){
      // grid x position
      positions[elementIndex][0] = x * gridElementSize; 
      // grid y position
      positions[elementIndex][1] = y * gridElementSize; 
      // increment element counter
      elementIndex++;
    }
  }
}

void draw(){
  background(0);
  // render all quads in one go
  beginShape(QUADS);
  for(int elementIndex = 0; elementIndex < numElements; elementIndex++){
      positions[elementIndex][0]  = lerp(positions[elementIndex][0] , mouseX, random(easeAmount));
      positions[elementIndex][1]  = lerp(positions[elementIndex][1] , mouseY, random(easeAmount));
      
      // render updated quad
      quad(positions[elementIndex][0], positions[elementIndex][1], gridElementSize);
  }
  endShape();
  
}

void quad(float x, float y, float size){
  float halfSize = size * 0.5;
  vertex(x            , y - halfSize); // top
  vertex(x + halfSize , y           ); // right
  vertex(x            , y + halfSize); // bottom
  vertex(x - halfSize , y           ); // left
}

可以自由地探索其他的选择。

它可能有助于将功能封装到一个可重用的类中,并使用PVector。如果这是目前的一个高级主题,请查看丹尼尔·谢夫曼的代码视频性质和(免费)在线书籍。

以下是对的Repeller示例的修改版本,以使用网格:

代码语言:javascript
复制
// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com

ParticleSystem ps;
Repeller repeller;

void setup() {
  size(600,600);
  strokeWeight(6);
  
  ps = new ParticleSystem(new PVector(width/2,50));
  repeller = new Repeller(width/2-20,height/2);
  
}

void draw() {
  repeller.position.set(mouseX, mouseY);
  
  background(255);
  
  ps.applyRepeller(repeller);
  
  ps.run();
}

void mousePressed(){
  repeller.G = -1000;
}

void mouseReleased(){
  repeller.G = 1000;
}

// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com

class Particle {
  PVector position;
  PVector velocity;
  PVector acceleration;
  float lifespan;
  
  float mass = 100; // Let's do something better here!
  
  PVector initialPosition;
  
  Particle(PVector l) {
    initialPosition = l.get();
    reset();
  }
  
  void reset(){
    acceleration = new PVector(0,0);
    velocity = new PVector();
    position = initialPosition.get();
    lifespan = 255.0;
  }

  void run() {
    update();
    display(g);
  }

  void applyForce(PVector force) {
    PVector f = force.get();
    f.div(mass);   
    acceleration.add(f);
  }

  // Method to update position
  void update() {
    velocity.add(acceleration);
    position.add(velocity);
    acceleration.mult(0);
    lifespan -= .2;
  }

  // Method to display
  void display(PGraphics g) {
    g.stroke(0,lifespan);
    g.vertex(position.x,position.y);
  }

  // Is the particle still useful?
  boolean isDead() {
    if (lifespan < 0.0) {
      return true;
    } else {
      return false;
    }
  }
}

// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com

class ParticleSystem {
  ArrayList<Particle> particles;
  PVector origin;
  
  int numParticles = 10000;
  int particleIndex = 0;

  ParticleSystem(PVector position) {
    origin = position.get();
    particles = new ArrayList<Particle>();
    for(int i = 0; i < numParticles; i++){
      addParticle();
    }
  }

  void addParticle() {
    particles.add(new Particle(new PVector(particleIndex % 100 * 6, particleIndex / 100 * 6)));
    particleIndex++;
  }

  // A function to apply a force to all Particles
  void applyForce(PVector f) {
    for (Particle p: particles) {
      p.applyForce(f);
    }
  }

  void applyRepeller(Repeller r) {
    for (Particle p: particles) {
      PVector force = r.repel(p);        
      p.applyForce(force);
    }
  }


  void run() {
    beginShape(POINTS);
    for (int i = particles.size()-1; i >= 0; i--) {
      Particle p = particles.get(i);
      p.run();
      if (p.isDead()) {
        //particles.remove(i);
        p.reset();
      }
    }
    endShape();
  }
}

// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com

// Particles + Forces

// A very basic Repeller class
class Repeller {
  
  // Gravitational Constant
  float G = 1000;
  // position
  PVector position;
  float r = 10;

  Repeller(float x, float y)  {
    position = new PVector(x,y);
  }

  void display() {
    stroke(0);
    strokeWeight(2);
    fill(175);
    ellipse(position.x,position.y,48,48);
  }

  // Calculate a force to push particle away from repeller
  PVector repel(Particle p) {
    PVector dir = PVector.sub(position,p.position);      // Calculate direction of force
    float d = dir.mag();                       // Distance between objects
    dir.normalize();                           // Normalize vector (distance doesn't matter here, we just want this vector for direction)
    d = constrain(d,5,100);                    // Keep distance within a reasonable range
    float force = -1 * G / (d * d);            // Repelling force is inversely proportional to distance
    dir.mult(force);                           // Get force vector --> magnitude * direction
    return dir;
  }  
}

注意粒子褪色(基于Particle的寿命),然后重置。

(这让人想起10年前我的一个朋友在JS中编码的一种效果:http://js1k.com/2011-trail/demo/908。它使用普通的JS,但在概念上仍然使用相当于一个类来表示每个具有控制速度和位置的属性的粒子)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71022793

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档