【问题标题】:How can I draw a SuperShape3D as a mesh?如何将 SuperShape3D 绘制为网格?
【发布时间】:2011-06-16 13:50:25
【问题描述】:

我想绘制一个 3D Superformula 网格,但不知道应该如何组织面(三角形或四边形)。

我已经安装了 octave 并尝试了示例代码。我不知道 Gnuplot 的 mesh() 函数是如何工作的,但我想我需要类似的东西。

维基百科条目有一个指向Processing demo 的链接。 我查看了源代码,发现它只画了点。 我试图将那段代码包装在beginShape()/endShape() 打电话,但按我希望的方式工作。

我还尝试检查点数是否可以被 3 整除 或 4 并使用 TRIANGLES 或 QUADS,但这不是正确的方法, 如下所示:

如何使用三角形/四边形绘制 SuperShape3D? 我想顶点在正确的位置,但他们 需要分类为使用绘制面部的调用 顶点索引。

目前我并没有固定在某种特定的语言上,但是 我的目标是将顶点放在一个数组中,然后 使用顶点索引推动面(3 或 4 点)。

有什么提示吗?

更新:

这是处理示例代码中用于获取点的函数:

import toxi.geom.*;
import controlP5.*;

ControlP5 controlP5;
ArrayList points = new ArrayList();
ArrayList faces = new ArrayList();

float a1=1,a2=1,b=1,xx,step = 0.05,yy,zz,n1=4,n2=12,n3=15,n4=15,r,raux1,r1,raux2,r2;
int N_X = int(2*PI/step);
int N_Y = int(PI/step);


void setup() {
  size(800,800,P3D);
  //hint(ENABLE_DEPTH_SORT);

  controlP5 = new ControlP5(this);

  controlP5.addSlider("a1value",0,3,1,20,0,200,10);
  controlP5.addSlider("a2value",0,3,1,20,20,200,10);
  controlP5.addSlider("bvalue",0,3,1,20,40,200,10);
  controlP5.addSlider("n1value",0,20,8,20,60,200,10);
  controlP5.addSlider("n2value",0,5,0.5,20,80,200,10);
  controlP5.addSlider("n3value",0,5,0.5,20,100,200,10);
  controlP5.addSlider("n4value",0,20,8,20,120,200,10);
  controlP5.addSlider("stepvalue",0.02,0.9,0.05,20,140,200,10);
  controlP5.setAutoDraw(false);
  draw_super_formula();
}

void draw() {
  background(0);
  fill(255);
  controlP5.draw();
  lights();
  translate(width / 2, height / 2, 0);
  rotateX(mouseY * 0.01f);
  rotateY(mouseX * 0.01f);
  // connect 4 points into quads:
  Vec3D pt;
  for(int x=0;x<N_X-1;x++)
  {
    for(int y=0;y<N_Y-1;y++)
    {
      beginShape(QUADS);
      pt = (Vec3D)points.get( x*N_Y + y );
      vertex(pt.x,pt.y,pt.z);
      pt = (Vec3D)points.get( x*N_Y + y+1 );
      vertex(pt.x,pt.y,pt.z);
      pt = (Vec3D)points.get( (x+1)*N_Y + y+1 );
      vertex(pt.x,pt.y,pt.z);
      pt = (Vec3D)points.get( (x+1)*N_Y + y);
      vertex(pt.x,pt.y,pt.z);
      endShape();
    }
  }
}

void vertex(Vec3D v) {
  vertex(v.x,v.y,v.z);
}

void draw_super_formula() {
  for(int i = points.size()-1; i>0;i--){
    points.remove(i);
  }

  for(int x=0;x<N_X;x++)
  {
    float i = -PI + x*step;
    for(int y=0;y<N_Y;y++)
    {
      float j = -PI/2.0 + y*step;
      raux1=pow(abs(1/a1*abs(cos(n1*i/4))),n3)+pow(abs(1/a2*abs(sin(n1*i/4))),n4);
      r1=pow(abs(raux1),(-1/n2));
      raux2=pow(abs(1/a1*abs(cos(n1*j/4))),n3)+pow(abs(1/a2*abs(sin(n1*j/4))),n4);
      r2=pow(abs(raux2),(-1/n2));
      xx=r1*cos(i)*r2*cos(j)*100;
      yy=r1*sin(i)*r2*cos(j)*100;
      zz=r2*sin(j)*100;

      Vec3D test1 = new Vec3D(xx,yy,zz);
      points.add(test1);
    }
  }
}

void bvalue(float new_value){
  b = new_value;
  draw_super_formula();
}
void a1value(float new_value){
  a1 = new_value;
  draw_super_formula();
}
void a2value(float new_value){
  a2 = new_value;
  draw_super_formula();
}
void n1value(float new_value){
  n1 = new_value;
  draw_super_formula();
}
void n2value(float new_value){
  n2 = new_value;
  draw_super_formula();
}
void n3value(float new_value){
  n3 = new_value;
  draw_super_formula();
}
void n4value(float new_value){
  n4 = new_value;
  draw_super_formula();
}

void stepvalue(float new_value){
  step = new_value;
  draw_super_formula();
  println("% 3: "+(points.size()%3));
  println("% 4: "+(points.size()%4));
}
class F4{
  int a,b,c,d;
  F4(int a,int b,int c,int d){
    this.a = a;
    this.b = b;
    this.c = c;
    this.d = d;
  }
}

@tim_hutton 的解决方案很棒,但它看起来像一个索引,试图找出它在哪里。

【问题讨论】:

    标签: 3d geometry computational-geometry mesh


    【解决方案1】:

    超公式为您提供了每个采样角度的半径。在 3D 中,您需要两个角度:theta 和 phi。通过保持 theta 固定和变化 phi(反之亦然),您将沿着一个大圆圈进行采样。

    制作曲面的一种方法是通过基于角度 a 和 b 对四个点进行采样来制作四边形:(a,b), (a+da,b), (a+da,b+db), ( a,b+db)。对 a: 0,da,2*da... 和 b: 0,db,2*db... 执行此操作,直到覆盖整个表面。使用小的 da 和 db 得到小的四边形。

    (替代方法是使用通用表面重建算法 (1,2),但这对于这样的问题来说太过分了。)

    更新:

    我认为下面的代码是你想要的:

    
    import toxi.geom.*;
    import controlP5.*;
    
    ControlP5 controlP5;
    ArrayList points = new ArrayList();
    ArrayList faces = new ArrayList();
    
    float a1=1,a2=1,b=1,xx,step = 0.05,yy,zz,n1=4,n2=12,n3=15,n4=15,r,raux1,r1,raux2,r2;
    int N_X = int(2*PI/step);
    int N_Y = int(PI/step);
    
    
    void setup() {
      size(800,800,P3D);
      //hint(ENABLE_DEPTH_SORT);
    
      controlP5 = new ControlP5(this);
    
      controlP5.addSlider("a1value",0,3,1,20,0,200,10);
      controlP5.addSlider("a2value",0,3,1,20,20,200,10);
      controlP5.addSlider("bvalue",0,3,1,20,40,200,10);
      controlP5.addSlider("n1value",0,20,8,20,60,200,10);
      controlP5.addSlider("n2value",0,5,0.5,20,80,200,10);
      controlP5.addSlider("n3value",0,5,0.5,20,100,200,10);
      controlP5.addSlider("n4value",0,20,8,20,120,200,10);
      controlP5.addSlider("stepvalue",0.02,0.9,0.05,20,140,200,10);
      controlP5.setAutoDraw(false);
      draw_super_formula();
    }
    
    void draw() {
      background(0);
      fill(255);
    
      controlP5.draw();
    
      translate(width / 2, height / 2, 0);
      rotateX(mouseY * 0.01f);
      rotateY(mouseX * 0.01f);
      drawAxes(300);
      beginShape(POINTS);
      for(int i = 0; i < points.size();i++){
        Vec3D k = (Vec3D)points.get(i); 
        stroke(color(k.x+110,k.y+110,k.z+110));
        vertex(k.x,k.y,k.z);
      }
      endShape();
    
      // connect 4 points into quads:
      Vec3D pt;
      noFill();
      for(int x=0;x<N_X-1;x++)
      {
        for(int y=0;y<N_Y-1;y++)
        {
          beginShape();
          pt = (Vec3D)points.get( x*N_Y + y );
          vertex(pt.x,pt.y,pt.z);
          pt = (Vec3D)points.get( x*N_Y + y+1 );
          vertex(pt.x,pt.y,pt.z);
          pt = (Vec3D)points.get( (x+1)*N_Y + y+1 );
          vertex(pt.x,pt.y,pt.z);
          pt = (Vec3D)points.get( (x+1)*N_Y + y);
          vertex(pt.x,pt.y,pt.z);
          endShape();
        }
      }
    }
    
    void vertex(Vec3D v) {
      vertex(v.x,v.y,v.z);
    }
    
    void draw_super_formula() {
      for(int i = points.size()-1; i>0;i--){
        points.remove(i);
      }
    
      for(int x=0;x<N_X;x++)
      {
        float i = -PI + x*step;
        for(int y=0;y<N_Y;y++)
        {
          float j = -PI/2.0 + y*step;
          raux1=pow(abs(1/a1*abs(cos(n1*i/4))),n3)+pow(abs(1/a2*abs(sin(n1*i/4))),n4);
          r1=pow(abs(raux1),(-1/n2));
          raux2=pow(abs(1/a1*abs(cos(n1*j/4))),n3)+pow(abs(1/a2*abs(sin(n1*j/4))),n4);
          r2=pow(abs(raux2),(-1/n2));
          xx=r1*cos(i)*r2*cos(j)*100;
          yy=r1*sin(i)*r2*cos(j)*100;
          zz=r2*sin(j)*100;
    
          Vec3D test1 = new Vec3D(xx,yy,zz);
          points.add(test1);
        }
      }
    }
    
    void drawAxes(float l) {
      stroke(255, 0, 0);
      line(0, 0, 0, l, 0, 0);
      line(l, 0, 0, l-10, 10, 0);
      line(l, 0, 0, l-10, -10, 0);
    
      stroke(0, 255, 0);
      line(0, 0, 0, 0, l, 0);
      line(0, l, 0, 10, l-10, 0);
      line(0, l, 0, -10, l-10, 0);
    
      stroke(0, 0, 255);
    
      line(0, 0, 0, 0, 0, l);
      line(0, 0, l, 0, 10, l-10);
      line(0, 0, l, 0, -10, l-10);
    
    }
    
    void bvalue(float new_value){
      b = new_value;
      draw_super_formula();
    }
    void a1value(float new_value){
      a1 = new_value;
      draw_super_formula();
    }
    void a2value(float new_value){
      a2 = new_value;
      draw_super_formula();
    }
    void n1value(float new_value){
      n1 = new_value;
      draw_super_formula();
    }
    void n2value(float new_value){
      n2 = new_value;
      draw_super_formula();
    }
    void n3value(float new_value){
      n3 = new_value;
      draw_super_formula();
    }
    void n4value(float new_value){
      n4 = new_value;
      draw_super_formula();
    }
    
    void stepvalue(float new_value){
      step = new_value;
      draw_super_formula();
      println("% 3: "+(points.size()%3));
      println("% 4: "+(points.size()%4));
    }
    class F4{
      int a,b,c,d;
      F4(int a,int b,int c,int d){
        this.a = a;
        this.b = b;
        this.c = c;
        this.d = d;
      }
    }
    

    【讨论】:

    • 通过对四个点进行采样来制作四边形的想法听起来不错。我害怕我不完全理解这些点的符号。 a,b 是两个角度(wiki 示例中的 theta 和 phi),d 是什么?它是四边形的第四点吗?我已经更新了我的问题。
    • 在你的代码中你几乎完成了。在完全按照你已经在做的那样循环 i 和 j 之后,从点 0,1,k+1,k 开始制作你的第一个四边形。其中 k 是每行中的样本数:PI/step。下一个四边形是 1,2,k+2,k+1 等,直到 k-2,k-1,2k-1,2k-2。这给了你一整列。然后执行下一列:k,k+1,2k+1,2k 等。希望这是有道理的!
    • 我已经添加了完整的代码 + 尝试存储四边形,但我害怕我做错了 :( 如果 k = PI/step ...那将是一个常数对吗?所以我想我不明白这部分...那么...0,1,k+1,k 将是顶点或顶点坐标的索引?感谢您花时间解释。
    • @tim_hutton 哇!这看起来很棒!最后一个小问题,有些面不见了,猜想和画四边形时的开始/结束索引有关,但不确定:(
    • 是的,您需要添加额外的四边形行和列,以环绕到每行/列的开头。使用 % 运算符。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-17
    • 2021-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-18
    相关资源
    最近更新 更多