workshop/of/STL

STLデータを扱う

STLデータは3Dプリンタにおいてスタンダードと言える3Dファイル形式です.3Dファイルとは言ってもこれだけでは キャラクタのアニメーションはもとよりテクスチャデータを扱うことはできない極めてシンプルなものです.一方で このデータ形式をプログラマブルに制御できればアプリケーションから3Dプリンタデータを容易に作成できます. このページではOpenframeworkを利用して,STLデータを扱うための情報をまとめます.

1. STLデータを作ってみる

まずはSTLデータを作ってみましょう.つくるといってもCADソフトからデータを作成するのではなく, テキストエディット(メモ帳)で作成してみます. まずはテキストエディットで下記内容をコピー&ペーストし,デスクトップに保存してください.

Sample.1
solid OBJECT
  facet normal 0 0 1
    outer loop
      vertex 0 0 0
      vertex 10 0 0
      vertex 10 10 0
    endloop
  endfacet
endsolid OBJECT

それではこの下の点線内部分がSTL Viewerになっているので,デスクトップからここへドラッグアンドドロップ してください.三角形が表示されればOKです.

それでは順に説明していきます.まず,STL形式はsolid で始まり,最後はendsolidで終わります. solidで一つの3Dオブジェクトを指しています.今回は3Dオブジェクトの名前をOBJECTとしていますが, これはどのような名前でも構いません.次の facet normalは法線ベクトルの方向を示しています.つまり この面の向きはどちらを向いているかを指す情報です.これはソリッドモデルを扱う際,その部分がソリッドモデルに なるのかを指す重要な情報です.この例ではz方向マイナスの向きを指しています.outer loopから頂点座標を 示します.3D形状を示すメッシュでは,三角形が基本メッシュとして扱われるため,すべて3点を基準に座標をしてい します.

【重要】法線方向について法線はnormalで指定されているとおりですが,実際にこれを様々な ソフトウェアで読み込む場合,座標系(x,y,zのそれぞれの正負の向き)が統一されていないといけません. つまり,このnormal情報だけでは,誤った法線方向を計算してしまう恐れがあります.この問題を解決するために 一つ大事な決まり事があります.vertexによって宣言された3頂点の順番によって,実は法線方向が決まる.ということです. なのでソフトウェアによってはnormal情報を単に0 0 0としてしまうものもあるようです.ではどのように座標がきまるかと いうと,下図1のように法線の向きに応じて座標を打つ順番が決まります.

図1. 法線と座標の順番の関係
練習1

紙面上に3次元座標を記述し,Sample.1で示される面を図示せよ.

練習2

Sample.1に3つの頂点を追加することで,四角形を作成せよ.作成したstlデータを上記STL Viewerで確認せよ.

練習3

10x10x10サイズの立方体データをstl形式で作成せよ.

立方体は6面あるため,それぞれを三角形のメッシュで構成するため合計で2*6=12面を記述する必要がある

ここまでで,STLデータ形式に関して一定の理解ができたかと思います.なおSTLデータ形式にはバイナリとASCIIの2種類がありますが, 今回利用したのはASCII形式です.ASCII形式はつまりテキストで記述する方式で,バイナリ方式は人間がそのままでは読めない(読みづらい)形式で 保存するものです.バイナリ形式はデータ量をASCII形式に比べて減らすことができます.それでは次の節ではOpenframeworksでメッシュデータを作成 してみます.

2. OFで作成した立方体をSTLデータにする

OFで基本的な立体図形を簡単に作成できます.まずは下記プログラムを実際にOFで実行してください.

ofApp.cpp

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
  box.set( 100 ); // 立方体のサイズを100x100x100
  box.setResolution(1); // もっともシンプルにトライアングルメッシュを作成
}

//--------------------------------------------------------------
void ofApp::update(){

}

//--------------------------------------------------------------
void ofApp::draw(){
  cam.begin(); // マウスのdrag & dropで視点移動を可能にする
  ofSetColor(0,0,0);
  box.drawWireframe();
  cam.end();
}


ofApp.h

#pragma once

#include "ofMain.h"

class ofApp : public ofBaseApp{
  
public:
  void setup();
  void update();
  void draw();
  
  ofBoxPrimitive box; // 立方体クラス
  ofEasyCam cam; // 3次元上に設置するカメラ

};

実行時の動画

簡単に立方体を作成して表示することができました.では,今度はこのデータをSTLに書き出してみます. STLデータ形式はすでに学習しましたが,これを描画するには,各トライアングルメッシュの頂点座標が必要と なります.法線ベクトルも必要ですが,結局のところ頂点座標から計算されるので,今回は0 0 0とすべて書き出すことにします.

ofApp.cpp

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
  box.set( 100 ); // 立方体のサイズを100x100x100
  box.setResolution(1); // もっともシンプルにトライアングルメッシュを作成
}

//--------------------------------------------------------------
void ofApp::update(){

}

//--------------------------------------------------------------
void ofApp::draw(){
  cam.begin(); // マウスのdrag & dropで視点移動を可能にする
  ofSetColor(0,0,0);
  box.drawWireframe();
  cam.end();
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
  if( key == ' ' ){
    triangles = box.getMesh().getUniqueFaces();
    cout << "solid test-of" << endl;
    
    for( int i = 0; i < triangles.size(); i++ ){
      cout << "facet normal 0 0 0" << endl;
      cout << "outer loop" << endl;
      
      for( int j = 0; j < 3; j++ ){
        cout << "vertex ";
        cout << triangles[i].getVertex(j).x << " ";
        cout << triangles[i].getVertex(j).y << " ";
        cout << triangles[i].getVertex(j).z << endl;
      }
      cout << "endloop" << endl;
      cout << "endfacet" << endl;
    }
    cout << "endsolid test-of" << endl;
  }
}

ofApp.h

#pragma once

#include "ofMain.h"

class ofApp : public ofBaseApp{
  
public:
  void setup();
  void update();
  void draw();
  
  void keyPressed(int key);
  ofBoxPrimitive box; // 立方体クラス
  ofEasyCam cam; // 3次元上に設置するカメラ

};

スペースキーを押すとXcodeのデバッグ窓にSTLデータ形式が出力されます. これをコピーして,1節と同じ要領でファイルに保存してください.先ほどのSTL Viewerでも よいですし,3Dプリンタ用のアプリケーションで実際に立方体が読み込めるか確認しましょう.


Copyright (c) 2015 Tetsuaki BABA all rights reserved.