提问者:小点点

如何从加工中心连接球体?


目前,我正在尝试连接在设定距离内的球体。我尝试使用line(x1, y1,z1,x2,y2,z2)函数,但这会产生一些随机的线条。然后我尝试使用贝塞尔,但我仍然得到奇怪的结果。

这是到目前为止的代码:

import peasy.*;

ArrayList<Position> positions;
int count=0;
int distanceToDrawLines = 20;
PeasyCam camera;

void setup() {
  size(1280, 720, P3D);
  stroke(255);
  positions = new ArrayList<Position>();
  smooth(8);
  lights();
}

void draw() {  
  float randomX, randomY, randomZ;
  //camera(mouseX, height/2, (height/2) / tan(PI/6), width/2, height/2, 0, 0, 1, 0);
  //camera = new PeasyCam(this, 0, 0, 0, 0);
  randomX = random(0, width);
  randomY = random(0, height);
  randomZ = random(0, 40);

  Position newPosition = new Position(new PVector(randomX, randomY, randomZ), 20);
  positions.add(newPosition);
  fill(255, 0, 0, 75);
  stroke(0);
  newPosition.Draw();


  for (int i=0; i<positions.size(); i++) {
    Position position = positions.get(i);
    noFill();
    beginShape();
    vertex(position.vector.x,position.vector.y,position.vector.z);
    if (position!=newPosition) {
      float d = dist(position.vector.x, position.vector.y, position.vector.z, newPosition.vector.x, newPosition.vector.y, newPosition.vector.z);

      if (d<=distanceToDrawLines && d!=0) {
        println(d, positions.size(), position.vector, newPosition.vector);
        bezierVertex(position.vector.x, position.vector.y, position.vector.z, newPosition.vector.x, newPosition.vector.y, newPosition.vector.z);
      }
    }
    endShape();
  }

}

位置类:

public class Position {
  public PVector vector;
  private boolean drawn;
  public float radius;

  public Position(PVector vector, float radius) {
    this.vector = vector;
    this.radius = radius;
  }

  public void DrawSphere() {
    if (!drawn) {
      fill(255, 0, 0, 75);
      noStroke();
      translate(vector.x, vector.y, vector.z);
      sphere(radius);
      fill(0);
      stroke(0);
      drawn = true;
    }
  }

  public void DrawEllipse() {
    if (!drawn) {
      fill(random(0,255), random(0,255), random(0,255), 75);
      noStroke();
      ellipse(vector.x, vector.y, radius, radius);
      point(vector.x, vector.y);
      fill(0);
      drawn = true;
    }
  }
}

任何帮助将不胜感激。

谢谢!


共1个答案

匿名用户

你还没有发布位置类,所以我假设它大致如下:

class Position{
  PVector vector;
  float radius;

  Position(PVector pos,float rad){
    vector = pos;
    radius = rad; 
  }

  void Draw(){
    pushMatrix();
    translate(vector.x,vector.y,vector.z);
    sphere(radius);
    popMatrix();
  }

}

有几件事似乎没有反映出你的意图:

  1. 绘制新帧时没有清除背景。这可能会导致在您旋转相机时到处都是线条,因为帧缓冲区未被清除。
  2. 相机目前已被注释掉,可能应该在settings()中初始化一次,而不是在draw()
  3. 中每帧多次初始化
  4. 每秒多次生成球体渲染成本很高,而且有点混乱:我建议限制最初生成的球体数量。也许这是你的count变量的意图?
  5. 这部分:

在一定距离内接近的球体

听起来有点不清楚。看起来距离没有设置,因为您在最近的位置实例中比较的距离之一位于随机位置。(除非您确实想将距离与最近的球体/位置实例进行比较)

除此之外,我只有一些简化此设置的提示:

>

  • 对随机值使用正负范围将有助于“居中”球体分布(因为只有正值才会使组向右移动)
  • 使用PVector的dist()做同样的事情

    dist(位置. vector.x、位置.vector.y、位置.vector.z、newPosition.vector.x、newPosition.vector.y、newPosition.vector.z);但保持语法更简洁:位置.vector.dist(newPosition.vector);

    您可以根据您的代码在修订和注释版本中尝试这些建议(使用向上/向下键更改距离阈值):

    in-processing
    import peasy.*;
    
    ArrayList<Position> positions;
    int count=0;
    
    //increase the distance threshold value: with a wider range of random values there will be less chances of spheres being so close to each other
    int distanceToDrawLines = 200;
    PeasyCam camera;
    
    //keep a reference to the most recent Position instance
    Position newPosition = null;
    
    void setup() {
      size(1280, 720, P3D);
      stroke(255);
      positions = new ArrayList<Position>();
      smooth(8);
      lights();
    
      //use simplified spheres (will look blockier, but will render faster)
      sphereDetail(5);
      //setup PeasyCam once in setup
      camera = new PeasyCam(this, 100);
      camera.setMinimumDistance(50);
      camera.setMaximumDistance(500);
    }
    
    void draw() {  
      background(127);
    
      //generate a limited amount of spheres
      if(count < 100){
    
        float randomX, randomY, randomZ;
        randomX = random(-width, width);
        randomY = random(-height, height);
        randomZ = random(-40, 40);
    
        newPosition = new Position(new PVector(randomX, randomY, randomZ), 20);
        positions.add(newPosition);
    
        count++;
      }
    
    
      for (int i=0; i<positions.size(); i++) {
        Position position = positions.get(i);
    
        noFill();
    
        if (position != newPosition) {
    
          float d = position.vector.dist(newPosition.vector);
    
          if (d<=distanceToDrawLines && d!=0) {
            println(d, positions.size(), position.vector, newPosition.vector);
            line(position.vector.x, position.vector.y, position.vector.z, newPosition.vector.x, newPosition.vector.y, newPosition.vector.z);
          }
        }else{
          //hightlight newest Position instance in transparent red
          fill(255, 0, 0, 75);
        }
        //render every Position instance (after the noFill() / fill() have been set
        position.Draw();
    
      }
    
    }
    //test - play with UP/DOWN arrows to tinker with distance
    void keyPressed(){
      if(keyCode == UP) distanceToDrawLines += 10;
      if(keyCode == DOWN) distanceToDrawLines -= 10;
      distanceToDrawLines = constrain(distanceToDrawLines,20,2000);
      println("distanceToDrawLines: " + distanceToDrawLines);
    }
    
    class Position{
      PVector vector;
      float radius;
    
      Position(PVector pos,float rad){
        vector = pos;
        radius = rad; 
      }
    
      void Draw(){
        pushMatrix();
        translate(vector.x,vector.y,vector.z);
        sphere(radius);
        popMatrix();
      }
    
    }
    

    这里的更新是一个示例,突出了注释中提到的一些优化概念。理想情况下,一些代码会移动到着色器,但值得使用jVisual alvm来跟踪当前执行的调用大部分时间并在那里开始优化。

    import peasy.*;
    
    ArrayList<Position> positions;
    Position newPosition;
    int count=0;
    int distanceToDrawLines = 500;
    PeasyCam cam;
    
    PShape nodes;
    
    int fcount, lastm;
    float frate;
    int fint = 3;
    
    void setup() {
      size(1280, 720, P3D);
      positions = new ArrayList<Position>();
      smooth(8);
      lights();
    
      //use simplified spheres (will look blockier, but will render faster)
      sphereDetail(0);//5
      frameRate(60);
      cam = new PeasyCam(this, 100);
      cam.setMinimumDistance(50);
      cam.setMaximumDistance(500);
    
      nodes = createShape(GROUP);
    
      while (count < 300) {
        float randomX, randomY, randomZ, randomRadius;
        randomX = random(-width*2, width*2);
        randomY = random(-height*2, height*2);
        randomZ = random(-1000*2, 1000*2);
        randomRadius = random(10, 40);
        newPosition = new Position(new PVector(randomX, randomY, randomZ), randomRadius);
        positions.add(newPosition);
        count++;
      }
      println("positions initialized");
    
      //calculate distances once, rather than multiple times per seconds
      //similarly instantiate geometries, which will simply be rendered in draw() 
      float distanceToDrawLinesSq = distanceToDrawLines * distanceToDrawLines;
      int numPositions = positions.size();
      for (int i=0; i<numPositions-1; i++) {
        for (int j=i+1; j<positions.size(); j++) {
          Position iPosition = positions.get(i);
          //iPosition.DrawSphere();
          nodes.addChild(getSphere(iPosition));
          Position jPosition = positions.get(j);
          //jPosition.DrawSphere();
          nodes.addChild(getSphere(jPosition));
          //cam.lookAt(iPosition.vector.x, iPosition.vector.y, iPosition.vector.z, 5);
    //      float d = iPosition.vector.dist(jPosition.vector);
    //      if (d <= distanceToDrawLines) {
          //using distance squared (more useful in draw() than setup though
          float dSq = PVector.sub(iPosition.vector,jPosition.vector).magSq();
          if (dSq <= distanceToDrawLinesSq) {
    
            PShape line = createShape(LINE,iPosition.vector.x, iPosition.vector.y, iPosition.vector.z, jPosition.vector.x, jPosition.vector.y, jPosition.vector.z);
            line.setStroke(color(255));
            line.setFill(false);
            nodes.addChild(line);
    
            //stroke(255);
            //line(iPosition.vector.x, iPosition.vector.y, iPosition.vector.z, jPosition.vector.x, jPosition.vector.y, jPosition.vector.z);
          }
        }
      }
      println("geometries initialized");
    
    }
    PShape getSphere(Position p){
        PShape sphere = createShape(SPHERE, 1.0);
        sphere.setStroke(false);
        sphere.setFill(p.fillColor);
        sphere.translate(p.vector.x,p.vector.y,p.vector.z);
        sphere.scale(p.radius);
        return sphere;
    }
    void draw() {  
      background(0);
    
      hint(DISABLE_DEPTH_TEST);
    
      pushMatrix();
      translate(width/2, height/2, -500);
      rotateY(frameCount * 0.01);
      rotateX(frameCount * 0.01);
    
      shape(nodes);
      popMatrix();
    
      hint(ENABLE_DEPTH_TEST);
    
      fcount += 1;
      int m = millis();
      if (m - lastm > 1000 * fint) {
        frate = float(fcount) / fint;
        fcount = 0;
        lastm = m;
        println("fps: " + frate);
      }
    
      //saveFrame("/output3/sequence####.tga");
      //saveFrame in separate thread
      TImage frame = new TImage(width,height,RGB,sketchPath("frame_"+nf(frameCount,3)+".tga"));
      frame.set(0,0,get());
      frame.saveThreaded();
    }
    
    class TImage extends PImage implements Runnable{//separate thread for saving images
      String filename;
    
      TImage(int w,int h,int format,String filename){
        this.filename = filename;
        init(w,h,format);
      }
    
      public void saveThreaded(){
        new Thread(this).start();
      }
    
      public void run(){
        this.save(filename);
      }
    
    }
    
    public class Position {
      private float speed;
      public PVector vector;
      public float radius;
      public int fillColor = color(200, 0, 0, 75);
    
      public Position(PVector vector, float radius) {
        this.vector = vector;
        this.radius = radius;
        this.speed = 0.05;
      }
    
      public void DrawSphere() {
        noStroke();
        vector.x+=random(-speed, speed);
        vector.y+=random(-speed, speed);
        vector.z+=random(-speed, speed);
        fill(fillColor);
        pushMatrix();
        translate(vector.x, vector.y, vector.z);
    
        sphere(radius);
        popMatrix();
      }
    
      public void DrawEllipse() {
        pushMatrix();
        translate(vector.x, vector.y, vector.z);
        ellipse(vector.x, vector.y, radius, radius);
        popMatrix();
      }
    }