日常の進捗

主に自分のための,行為とその習慣化の記録

Mod:Coding Challenge #9: Solar System in Processing - Part 3 (3D textures)

f:id:takawo:20170907235400g:plain

昨日の3Dの続き、テクスチャを球体にマッピングする方法。PShape使うのは知らなかった。応用効きそう。どっちかというとマッピングするテクスチャ画像の用意のほうが大変か。

複数のファイルの名前を意識しないで読み込むやりかたは、以前hysyskがやっていたJavaインターフェイスのオーバーライドでやるやつを参考にした。便利。

hysysk.blogspot.jp

画像自体はチュートリアルにもあるけど、以下のWebサイトで公開されているものをダウンロードした。

planetpixelemporium.com

import peasy.*;
import peasy.org.apache.commons.math.*;
import peasy.org.apache.commons.math.geometry.*;


File[] imageFiles;
JPGFileFilter filter;
PImage[] textures;
PImage sunTexture;

Planet sun;
PeasyCam cam;

// setup関数 : 初回1度だけ実行される
void setup() {
  size(960, 540, P3D); // ウィンドウサイズを960px,540pxに
  colorMode(HSB, 360, 100, 100, 100); // HSBでの色指定にする

  sunTexture = loadImage("sunmap.jpg");
  filter = new JPGFileFilter();
  imageFiles = new File(dataPath("")).listFiles(filter);
  textures = new PImage[imageFiles.length];
  for (int i = 0; i < imageFiles.length; i++) {
    textures[i] = loadImage(imageFiles[i].getName());
  }

  cam = new PeasyCam(this, 500);
  sun = new Planet(100, 0, 0, sunTexture);
  sun.spawnMoons(10, 1);
}

// draw関数 : setup関数実行後繰り返し実行される
void draw() {
  background(0, 0, 0);
  ambientLight(0, 0, 50);
  pointLight(0, 0, 50, 0, 0, 0);
  sun.draw();
  sun.orbit();
}
class Planet {
  float radius;
  float distance;
  Planet[] planets;
  float angle;
  float orbitSpeed;
  PVector v;
  PShape globe;
  color c;

  Planet(float r, float _d, float o, PImage img) {
    v = PVector.random3D();
    radius = r;
    angle = random(TWO_PI);
    distance  = _d;
    v.mult(distance);
    orbitSpeed = o;
    noStroke();
    noFill();
    globe = createShape(SPHERE, radius);
    globe.setTexture(img);
  }

  void spawnMoons(int total, int level) {
    planets = new Planet[total];
    for (int i = 0; i < planets.length; i++) {
      float r = radius/(level*2);
      float d = random((radius + r), (radius+r)*4);
      float o = random(-0.01, 0.01);
      int index = int(random(0, textures.length));
      planets[i] = new Planet(r, d, o, textures[index]);
      if (level < 2) {
        int num = int(random(0, 3));
        planets[i].spawnMoons(num, level+1);
      }
    }
  }
  void orbit() {
    angle = angle + orbitSpeed;
    if (planets != null) {
      for (int i = 0; i < planets.length; i++) {
        planets[i].orbit();
      }
    }
  }

  void draw() {
    pushMatrix();
    PVector v2 = new PVector(1, 0, 1);
    PVector p = v.cross(v2);
    rotate(angle, p.x, p.y, p.z);
    translate(v.x, v.y, v.z);
    noStroke();
    fill(0, 0, 100);
    shape(globe);
    if (planets != null) {
      for (int i = 0; i < planets.length; i++) {
        planets[i].draw();
      }
    }
    popMatrix();
  }
}

import java.io.File;
import java.io.FilenameFilter;

public class JPGFileFilter implements FilenameFilter {
  @Override
    public boolean accept(File directory, String fileName) {
    if (fileName.endsWith(".jpg")) {
      return true;
    }
    return false;
  }
}

リファレンス