Hemeshチュートリアル その1

More than 1 year has passed since last update.

HemeshはProcessingで3Dオブジェクトを作る時に役に立つライブラリです。

githubはこちら


基本的な紹介

Hemeshはhalf-edged mesh geometryの略で、立体を表現する際にhalf-edged mesh geometryという方式を利用しています。

(half-edged mesh geometryについてはこちら)

Hemeshで扱うクラスには基本的に4種類あって、全ての形を


  • HE_ : メッシュ関係のデータ

  • HEC_ : 基本的な幾何学・配置

の2種類のクラスで作ります。

そして、HEM_クラスで変形等を指定します。WBクラスというものが演算・レンダリングを担当します。


基本ロジック

HE_Meshでメッシュ初期化して、HEC_でメッシュを作るというのが基本。

HE_Meshではコアとなるデータにアクセスできるし、HEC_ではいろんな形と、それに関係するメソッドにアクセスできます。

例えばHEC_Cubeクラスを使うとedge, segment height, width, depth, inner/mid/outer radius等のメソッドを使うことができます。


サンプルプログラム


A_cube_basic_setup.pde

/*

PLEASE READ INTRO TAB
*/

/////////////////////////// GLOBALS ////////////////////////////
// LIBRARY IMPORT
import wblut.math.*;
import wblut.processing.*;
import wblut.core.*;
import wblut.hemesh.*;
import wblut.geom.*;
import processing.opengl.*;

// HEMESH CLASSES & OBJECTS
HE_Mesh MESH; // Our mesh object
WB_Render RENDER; // Our render object

// CAM
import peasy.*;
PeasyCam CAM;

/////////////////////////// SETUP ////////////////////////////

void setup() {
size(800, 600, OPENGL);
CAM = new PeasyCam(this, 150);

// OUR CREATOR
HEC_Cube creator = new HEC_Cube();

//CREATOR PARMAMETERS
creator.setEdge(70); // edge length in pixels

MESH = new HE_Mesh(creator); // add our creator object to our mesh object
RENDER = new WB_Render(this); // RENDER object initialise
}

/////////////////////////// DRAW ////////////////////////////
void draw() {
background(255);
// CAMERA
CAM.beginHUD(); // this method disables PeasyCam for the commands between beginHUD & endHUD
directionalLight(255, 255, 255, 1, 1, -1);
directionalLight(127, 127, 127, -1, -1, 1);
CAM.endHUD();

// HEMESH
// We draw our faces using the RENDER object
noStroke();
fill(0, 255, 255);
RENDER.drawFaces( MESH ); // Draw MESH faces

stroke(255, 0, 0);
RENDER.drawEdges( MESH ); // Draw MESH edges
}


実行結果

スクリーンショット 2016-08-11 19.57.15.png


セットアップ

まずglobalで


HE_Mesh MESH;


を宣言。

そして、processingのsetup()関数内で


HEC_Cube creator = new HEC_Cube();


のようにメッシュを作るobjectをつくった後、


MESH = new HE_Mesh(creator);


としてHE_Meshインスタンスとしてコールします。

また、WB_Renderクラスはライブラリ内の全ての関数を提供するもので、コードの最初に初期化しておきます。画面への結果表示にも使います。


  1. globalで WB_Render RENDER;

  2. setup();で RENDER = new WB_Render(this);

  3. draw();で RENDER.drawFaces( MESH ); // Notice we add the mesh object within the parentheses.


PeasyCam

座標変換やマウスとのインタラクション用にPeasyCamライブラリも使うと吉です。

http://mrfeinberg.com/peasycam/


基本メソッド

HEC_Cube creatorのメソッドを紹介します。


B_cube_basic_setup.pde

/*

PLEASE READ INTRO TAB
*/

/////////////////////////// GLOBALS ////////////////////////////
// LIBRARY IMPORT
import wblut.math.*;
import wblut.processing.*;
import wblut.core.*;
import wblut.hemesh.*;
import wblut.geom.*;
import processing.opengl.*;

// HEMESH CLASSES & OBJECTS
HE_Mesh MESH; // Our mesh object
WB_Render RENDER; // Our render object

// CAM
import peasy.*;
PeasyCam CAM;

/////////////////////////// SETUP ////////////////////////////

void setup() {
size(800, 600, OPENGL);
CAM = new PeasyCam(this, 150);

// OUR CREATOR
HEC_Cube creator = new HEC_Cube();

//CREATOR PARMAMETERS
creator.setEdge(70); // edge length in pixels
creator.setWidthSegments(4).setHeightSegments(4).setDepthSegments(4); // keep these small

//alternatively
//creator.setRadius(50);
//creator.setInnerRadius(50);// radius of sphere inscribed in cube
//Try these two
//creator.setOuterRadius(25);// radius of sphere circumscribing cube
//creator.setMidRadius(10);// radius of sphere tangential to edges

// These params set the initial position & need to be initialised seperately
// from other params such as height / setWidthSegments / edges ...
creator.setCenter(0, 0, 0).setZAxis(1, 1, 1).setZAngle(PI/4);

MESH = new HE_Mesh(creator);

//MESH.triangulate(); // this is one of many methods we can access from the HE_Mesh class
RENDER = new WB_Render(this); // RENDER object initialise
}

/////////////////////////// DRAW ////////////////////////////
void draw() {
background(255);
// CAMERA
CAM.beginHUD(); // this method disables PeasyCam for the commands between beginHUD & endHUD
directionalLight(255, 255, 255, 1, 1, -1);
directionalLight(127, 127, 127, -1, -1, 1);
CAM.endHUD();

// HEMESH
// We draw our faces, vertices and edges using the RENDER object
noStroke();
fill(0, 0, 255);
RENDER.drawFaces( MESH ); // Draw MESH faces

fill(0, 255, 0);
RENDER.drawVertices( 2, MESH ); // Draw MESH vertices

stroke(255,0,0);
RENDER.drawEdges( MESH ); // Draw MESH edges
//RENDER.drawFaceNormals( 10, MESH );
}

void keyPressed() {
if (key == 's') {
saveFrame("screenShot_###.png");
println("screen shot taken");
}

}


実行結果

スクリーンショット 2016-08-11 20.57.03.png

draw();内にfaces, edges, vertices, normals(法線)を見るためのメソッドも含んでいます。


RENDER.drawFaces( MESH );

RENDER.drawVertices( 2, MESH );

RENDER.drawEdges( MESH );

RENDER.drawFaceNormals( 10, MESH );


setup()でコメントアウトしているtriangulationメソッドをアクティベートすると、cubesが違う方法で描画されるようになるのがわかります。上記メソッドはデパッグにも便利です。

スクリーンショット 2016-08-11 20.58.57.png

drawVertex, drawVertexNormalsとかも便利そうです。


Modifires

Modifiersを使うには、まずHEM_modifierクラスを選択して、いろいろパラメータをいじって、modify()を実行してメッシュに反映させます。


C_cube_modif_extrude.pde

/*

PLEASE READ INTRO TAB
*/

/////////////////////////// GLOBALS ////////////////////////////
// LIBRARY IMPORT
import wblut.math.*;
import wblut.processing.*;
import wblut.core.*;
import wblut.hemesh.*;
import wblut.geom.*;
import processing.opengl.*;

// HEMESH CLASSES & OBJECTS
HE_Mesh MESH; // Our mesh object
WB_Render RENDER; // Our render object

// CAM
import peasy.*;
PeasyCam CAM;

/////////////////////////// SETUP ////////////////////////////

void setup() {
size(800, 600, OPENGL);
CAM = new PeasyCam(this, 400);

// OUR CREATOR
HEC_Cube creator = new HEC_Cube();

//CREATOR PARMAMETERS
creator.setEdge(70);
creator.setCenter(0, 0, 0).setZAxis(1, 1, 1).setZAngle(PI/4);
// Activate this line to see what happens
//creator.setWidthSegments(4).setHeightSegments(4).setDepthSegments(4); // keep these small

MESH = new HE_Mesh(creator); // add our creator object to our mesh object

// MODIFIER : SIMPLE EXTRUSION MODIFIER
HEM_Extrude extrude = new HEM_Extrude().setDistance(70);
MESH.modify( extrude ); // ADD OUR MODIFIER TO THE MESH

RENDER = new WB_Render(this);
}

/////////////////////////// DRAW ////////////////////////////
void draw() {
background(255);
// CAMERA
CAM.beginHUD();
directionalLight(255, 255, 255, 1, 1, -1);
directionalLight(127, 127, 127, -1, -1, 1);
CAM.endHUD();

// HEMESH
// To visualise better what is happening, I've activated the edges and disactivated the faces.
/*
noStroke();
fill(0, 0, 255);
RENDER.drawFaces( MESH ); // Draw MESH faces
*/

stroke(0, 0, 255);
strokeWeight(5);
RENDER.drawEdges( MESH ); // Draw MESH edges
}

void keyPressed() {
if (key == 'r') {
setup();
}
if (key == 's') {
saveFrame("screenShot.png");
}
}


実行結果

スクリーンショット 2016-08-11 21.03.26.png

要は押し出しです


HEM_Extrude extrude = new HEM_Extrude().setDistance(70);

MESH.modify( extrude ); // ADD OUR MODIFIER TO THE MESH


segment width, height, depthはデフォルトでは1です。

creator.setWidthSegments(4).setHeightSegments(4);

などと指定すると、

スクリーンショット 2016-08-11 21.07.45.png

こんな風になります。


Modifierの組み合わせ


C_cube_modif_chamfer.pde

/*

PLEASE READ INTRO TAB
*/

/////////////////////////// GLOBALS ////////////////////////////
// LIBRARY
import wblut.math.*;
import wblut.processing.*;
import wblut.core.*;
import wblut.hemesh.*;
import wblut.geom.*;
import processing.opengl.*;

// HEMESH CLASSES & OBJECTS
HE_Mesh MESH; // Our mesh object
WB_Render RENDER; // Our render object
HEC_Cube creator; // Our creator object

// CAM
import peasy.*;
PeasyCam CAM;

/////////////////////////// SETUP ////////////////////////////

void setup() {
size(800, 600, OPENGL);
CAM = new PeasyCam(this, 150);

creator = new HEC_Cube(); // Our creator

//CREATOR PARMAMETERS
creator.setEdge(60);
MESH = new HE_Mesh(creator); // ADD OUR CREATOR PARAMETERS TO OUR MESH

// SIMPLE CHAMFER MODIFIER
HEM_ChamferCorners chamfer = new HEM_ChamferCorners().setDistance(20);
HEM_ChamferEdges edges = new HEM_ChamferEdges().setDistance(5);

MESH.modify( chamfer ); // ADD OUR MODIFIER TO THE MESH
MESH.modify( edges );

RENDER = new WB_Render(this); // RENDER MESH
}

/////////////////////////// DRAW ////////////////////////////
void draw() {
background(255);
//CAMERA
CAM.beginHUD(); // this method disables PeasyCam for the commands between beginHUD & endHUD
directionalLight(255, 255, 255, 1, 1, -1);
directionalLight(127, 127, 127, -1, -1, 1);
CAM.endHUD();

//HEMESH
/*
noStroke();
fill(0, 0, 255);
RENDER.drawFaces( MESH ); // Draw MESH faces
*/

stroke(0, 0, 255);
strokeWeight( 5 );
RENDER.drawEdges( MESH ); //Draw MESH edges

}

// SOME KEYS INTERACTION
void keyPressed() {

if (key == 'e') {
// Hemesh includes a method for exporting geometry
// in stl file format wich is very handy for 3D printing ;–)
HET_Export.saveToSTL(MESH, sketchPath("export.stl"), "test");
}

if (key == 's') {
saveFrame("screenShot_###.png");
println("screen shot taken");
}
if (key == 'o') {
// reset camera origin positions - do this before
// exporting your shape so your shape is positioned
// on a flat plane ready for 3D printing
CAM.reset(1000);
}
// Print camera position - could be helpful
if (key == 'p') {
float[] camPos = CAM.getPosition();
println(camPos);
}
}


実行結果

スクリーンショット 2016-08-11 21.22.11.png

chamferの数値をいじるとちがった形にもなります。

スクリーンショット 2016-08-11 21.24.13.png

ここでstlに書き出そうとすると、壊れてしまいました。

スクリーンショット 2016-08-11 21.24.59.png

これは保存する前にMESH.triangulate()を実行することで解決できました。

スクリーンショット 2016-08-11 21.28.16.png

ここにチュートリアルがあります。