2

3Dスーパーフォーミュラメッシュを描画したいのですが、面(三角形または四角形)をどのように編成する必要があるかわかりません。

Octaveをインストールして、サンプルコードを試しました。Gnuplotのmesh()関数がどのように機能するかはわかりませんが、似たようなものが必要になると思います。

ウィキペディアのエントリには、処理デモへのリンクがあります。ソースを見てみると、ポイントを引くだけであることに気づきました。コードのそのセグメントを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のソリューションは素晴らしいですが、それがどこにあるかを理解しようとして、インデックスが外れているように見えます。

スーパーフォーミュラの問題

4

1 に答える 1

1

スーパーフォーミュラは、サンプリングされた各角度の半径を示します。3Dでは、シータとファイの2つの角度が必要です。シータを固定してファイを変化させる(またはその逆)ことにより、大円に沿ってサンプリングします。

サーフェスを作成する1つの方法は、角度aとbに基づいて4つのポイントをサンプリングして四角形を作成することです:(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;
  }
}
于 2011-01-27T14:50:28.410 に答える