正多面体の宝石箱


2018年02月27日
With
正多面体の宝石箱 はコメントを受け付けていません。

前回の「新たな描き順問題」に気がついたのは、実はこのスケッチを作ろうと作業している時のことでした。

●正多面体の宝石箱(クリックすると別タブが開きます)

正多面体のobjデータを作ってWebGLモードで表示していたのですが、「半透明で、強めの反射が出るようにしてクルクル回せば宝石のように光って見えるのではないか?」と思ったのですね。カメラ、ライト、マテリアルの設定をいろいろいじって、こんな感じにしてみました。多面体の回転を分かりやすくするために、strokeも薄くいれています。

ピンクっぽいのは不透明、緑っぽいのと黄色っぽいのは半透明にしています。問題回避用のArray.sortも入れて「半透明の多面体から向こう側を透かしてみる」ような描画も正しく行われるようになっているかと思います。今回のスケッチにはないのですが、そのうちオブジェクト同士の衝突判定なども入れてみようかと。

var sphereArr = [];
var spCount = 60;
var crystals = [];

function preload() {
    crystals[0] = loadModel('poly04.obj', true);
    crystals[1] = loadModel('poly08.obj', true);
    crystals[2] = loadModel('poly20.obj', true);
}

function setup() {
    createCanvas(600, 600, WEBGL);
    document.body.style.backgroundColor = '#ffffff';
    ambientLight(160);
    directionalLight(200, 200, 200, 255, -1, 1, -1);
    pointLight(255, 255, 255, 255, -200, -500, 200);
    stroke(220);
    strokeWeight(.5);
    for (var i = 0; i < spCount; i++) {
        sphereArr[i] = new Spr();
    }
}

function draw() {
    background(255);
    orbitControl();
    sphereArr.forEach(allSp => { allSp.updateMe(); });
    sphereArr.sort(zOrder);
    sphereArr.forEach(allSp => { allSp.drawMe(); });
}

function zOrder(obj1, obj2) {
    return obj1.z - obj2.z;
}


class Spr {
    constructor() {
        this.x = random(-100, 100);
        this.y = random(-100, 100);
        this.z = random(-1000, 100);
        this.r = 50;
        this.xmov = random(-2, 2);
        this.ymov = random(-2, 2);
        this.zmov = random(-2, 2);
        this.xrot = random(0, 359);
        this.yrot = random(0, 359);
        this.zrot = random(0, 359);
        this.xrotdiff = random(-2, 2);
        this.yrotdiff = random(-2, 2);
        this.zrotdiff = random(-2, 2);
        this.trans = floor(random(0, 3));
        this.shape = floor(random(0, 3));
    }
    updateMe() {
        this.x += this.xmov;
        this.y += this.ymov;
        this.z += this.zmov;
        if (this.x < -300 || this.x > 300) { this.xmov *= -1; }
        if (this.y < -300 || this.y > 300) { this.ymov *= -1; }
        if (this.z < -2000 || this.z > 300) { this.zmov *= -1; }
        this.xrot += this.xrotdiff;
        this.yrot += this.yrotdiff;
        this.zrot += this.zrotdiff;
    }
    drawMe() {
        push();
        translate(this.x, this.y, this.z);
        rotateX(radians(this.xrot));
        rotateY(radians(this.yrot));
        rotateZ(radians(this.zrot));
        if (this.trans == 0) {
            specularMaterial(180, 255, 200, 128);
        } else if (this.trans == 1) {
            specularMaterial(250, 250, 128, 128);
        } else {
            specularMaterial(255, 128, 192, 255);
        }
        scale(.6);
        model(crystals[this.shape]);
        pop();
    }
}