For openFrameworks Users

openFrameworks
ジャンキーのための
TrussC入門

oFが好きなあなたなら、TrussCも気に入るはず。
同じ楽しさを、現代の技術で。

TrussCは、openFrameworksが築き上げた「クリエイティブコーディングの楽しさ」を深くリスペクトしています。

でも、oFが設計された2000年代と今では、ハードウェアもC++も大きく変わりました。
TrussCは、oFの精神を継承しながら、現代の環境に最適化した「次の10年の足場」です。

変わらないもの

oFユーザーなら、違和感なく書き始められます

setup, update, draw

クリエイティブコーディングの基本リズム。この構造は不変です。

ofApp tcApp

見たことあるメソッド名

使い心地を極力変えないように、手に馴染んだメソッド名を踏襲しています。

ofDrawCircle(x, y, r) drawCircle(x, y, r)

VSCode 対応

今となっては標準ですよね。Cursor派ですか?もちろん大丈夫です。

CMake + clangd

oFで困っていたこと、解決しました

長年のペインポイントに対するTrussCの回答

困っていたこと

太線が描けない問題

ofSetLineWidth() はOpenGLの制限で太さ1px以上が保証されない。
macOS / Metal環境では完全に無視される。太い線を描くには自前でメッシュを生成するしかなかった。

TrussCの解決策

StrokeMesh で美しい太線

oFでは太い線を描くと角や終端がプッツリ切れた見た目になっていました。
StrokeMesh を使えば美しいエッジを持った幅のある線を描画できます。

// StrokeMesh で任意の太さの線が描ける
StrokeMesh stroke;
stroke.setStrokeWidth(5.0f);  // 5px の太線
stroke.moveTo(0, 0);
stroke.lineTo(100, 100);
stroke.draw();

// Polyline からも生成可能
Polyline line;
line.addVertex(0, 0);
line.addVertex(100, 50);
StrokeMesh stroke2(line, 3.0f);
stroke2.draw();
困っていたこと

親子関係の管理が面倒

ofNode はあるが、親子関係の管理が手動。
子ノードの追加・削除でメモリ管理が複雑。
親が消えても子が残ってしまう問題も。

TrussCの解決策

shared_ptr ベースで自動管理

// shared_ptr ベースで自動管理
auto parent = Node::create();
auto child = Node::create();
parent->addChild(child);

// 親を破棄すれば子も自動的に解放される
// 循環参照も weak_ptr で安全に回避
困っていたこと

回転したオブジェクトのクリック判定が地獄

マウス座標は常にスクリーン座標(左上原点)。
回転・スケールしたオブジェクト上のクリック判定は複雑な計算が必要。
ofNode を使っても座標変換は自分で計算するしかなかった。

TrussCの解決策

自動でローカル座標に変換

// RectNode は自動的にローカル座標に変換
class MyButton : public RectNode {
    void onMousePressed(const Vec2& localPos, int button) override {
        // localPos は「このノードにとっての」座標
        // 親が回転していても、自分のローカル座標で届く!
        if (localPos.x < width/2) {
            // 左半分をクリック
        }
    }
};
困っていたこと

重なったオブジェクトの判定が面倒

複数のオブジェクトが重なっているときの判定が面倒。
Zオーダー(描画順)を考慮した判定は自前実装するしかなかった。

TrussCの解決策

Zオーダー考慮 & イベント消費

// RectNode は自動的に Z オーダーを考慮
// 手前のノードが優先的にイベントを受け取る

void onMousePressed(const Vec2& pos, int button) override {
    // このノードで処理したら、後ろのノードには届かない
    consumeEvent();
}
困っていたこと

「3秒後に実行」を安全にやる方法がない

ofThread はデータ競合を起こしやすい。
「3秒後に実行」を安全にやる標準的な方法がなく、
update内で時間計測してif文を書くとコードが汚くなる。

TrussCの解決策

メインスレッドで安全な同期タイマー

// メインスレッドで安全に遅延実行
node->callAfter(3.0f, []() {
    // 3秒後にメインスレッドで実行
    // Mutex 不要、データ競合の心配なし
});

// 繰り返し実行も簡単
node->callEvery(1.0f, []() {
    // 1秒ごとに実行
});
困っていたこと

OpenGLがmacOSで非推奨に

AppleがOpenGLを非推奨にし、Metalへ移行。
将来的な動作保証やパフォーマンス最適化が困難に。
いつサポートが切れるかわからない不安。

TrussCの解決策

Sokolでネイティブバックエンド

Metal / DirectX 12 / Vulkan / WebGPU に対応。
OSが推奨する最新のネイティブAPI上で動作するため、高速かつ省電力。
WebAssembly + WebGPU でブラウザへの移植性も高い。

困っていたこと

商用利用でのライセンス問題

oF本体はMITだが、依存ライブラリにGPLが混在。
FFmpegやFreeTypeなど、ライセンスを確認するのが大変。
クライアントワークで使うときに不安が残る。

TrussCの解決策

MIT / zlib / Public Domain のみ

GPL汚染ゼロを徹底。
すべての依存ライブラリが商用利用フレンドリー。
安心してクライアントワークに使える。

困っていたこと

UpdateとDrawが常に連動する問題

ofSetFrameRate() はDrawとUpdateが常に連動。
物理シミュレーションを固定タイムステップで回したいときに困る。
イベント駆動型アプリ(ボタンを押したときだけ再描画)も作りにくかった。

TrussCの解決策

Update と Draw を独立制御

デフォルトでは今まで通りupdate, drawを交互に呼び出すこともできますが、イベント駆動型のUIアプリを作るときに無駄なdrawを避けるためにupdateとは別のタイミング(クリック時など)で実行できます。
また、描画負荷が重いアプリでもupdateを固定周期にすることも可能です。

// Draw と Update を独立制御
setDrawVsync(true);    // 描画は VSync (60Hz)
setUpdateFps(120);      // 物理更新は 120Hz

// イベント駆動型(省電力モード)
setDrawFps(0);          // 自動描画を停止
// mousePressed 等で redraw() を呼ぶと描画される

API対応表

oFの関数、TrussCではこう書く

アプリ構造

openFrameworks TrussC 備考
ofApp : public ofBaseApptcApp : public App
ofRunApp(new ofApp())runApp<tcApp>()テンプレート形式
setup()setup()同じ
update()update()同じ
draw()draw()同じ
keyPressed(int key)keyPressed(int key)同じ
mousePressed(x, y, button)mousePressed(x, y, button)同じ
windowResized(w, h)windowResized(w, h)同じ
dragEvent(ofDragInfo)filesDropped(paths)
ofSetFrameRate(60)setFps(60)
ofSetVerticalSync(true)setVsync(true)
-setDrawFps(fps)描画レート個別設定
-setUpdateFps(fps)更新レート個別設定
ofGetElapsedTimef()getElapsedTime()
ofGetFrameRate()getFrameRate()
ofGetFrameNum()getFrameCount()
ofGetWidth()getWindowWidth()
ofGetHeight()getWindowHeight()
OF_EXIT_APP()exitApp()アプリ終了

描画(Graphics)

openFrameworks TrussC 備考
ofBackground(r, g, b)clear(r, g, b)0.0-1.0
ofSetColor(r, g, b, a)setColor(r, g, b, a)0.0-1.0
ofSetColor(ofColor::red)setColor(colors::red)
ofDrawRectangle(x, y, w, h)drawRect(x, y, w, h)
ofDrawCircle(x, y, r)drawCircle(x, y, r)
ofDrawEllipse(x, y, w, h)drawEllipse(x, y, w, h)
ofDrawLine(x1, y1, x2, y2)drawLine(x1, y1, x2, y2)
ofDrawTriangle(...)drawTriangle(...)
ofNoFill()noFill()
ofFill()fill()
ofSetLineWidth(w)setLineWidth(w)
ofDrawBitmapString(s, x, y)drawBitmapString(s, x, y)
ofPolylinePath
-StrokeMesh太線描画
ofEnableBlendMode()setBlendMode()
ofScissor()setScissor()

変換(Transform)

openFrameworks TrussC 備考
ofPushMatrix()pushMatrix()
ofPopMatrix()popMatrix()
ofTranslate(x, y, z)translate(x, y, z)
ofRotateDeg(deg)rotateDeg(deg)
ofRotateRad(rad)rotateRad(rad)
ofScale(x, y, z)scale(x, y, z)

数学(Math)

openFrameworks TrussC 備考
glm::vec2 / ofVec2fVec2
glm::vec3 / ofVec3fVec3
glm::vec4 / ofVec4fVec4
glm::mat4 / ofMatrix4x4Mat4
ofMap(v, a, b, c, d)map(v, a, b, c, d)
ofClamp(v, min, max)clamp(v, min, max)
ofLerp(a, b, t)lerp(a, b, t)
ofNoise(x)noise(x)Perlin noise
ofSignedNoise(x)signedNoise(x)
ofRandom(min, max)random(min, max)
ofDegToRad(deg)radians(deg)
ofRadToDeg(rad)degrees(rad)
PIPI
TWO_PITAUτ = 2π

色(Color)

openFrameworks TrussC 備考
ofColor(r, g, b, a)Color(r, g, b, a)0.0-1.0
ofColor::fromHsb(h, s, b)Color::fromHSB(h, s, b)0.0-1.0
-Color::fromOKLab(L, a, b)OKLab色空間
-Color::fromOKLCH(L, C, h)OKLCH色空間

画像(Image)

openFrameworks TrussC 備考
ofImageImage
img.load("path")img.load("path")同じ
img.draw(x, y)img.draw(x, y)同じ
img.draw(x, y, w, h)img.draw(x, y, w, h)同じ
img.save("path")img.save("path")同じ
img.getWidth()img.getWidth()同じ
img.getHeight()img.getHeight()同じ
img.setColor(x, y, c)img.setColor(x, y, c)同じ
img.getColor(x, y)img.getColor(x, y)同じ
-img.setFilter(Nearest/Linear)テクスチャフィルター
-img.setWrap(Repeat/Clamp/...)テクスチャラップ

フォント(Font)

openFrameworks TrussC 備考
ofTrueTypeFontTrueTypeFont
font.load("font.ttf", size)font.load("font.ttf", size)
font.drawString(s, x, y)font.drawString(s, x, y)
-drawBitmapString(s, x, y)組み込みフォント

3Dプリミティブ

openFrameworks TrussC 備考
ofPlanePrimitivecreatePlane(w, h)Meshを返す
ofBoxPrimitivecreateBox(size)
ofSpherePrimitivecreateSphere(r, res)
ofIcoSpherePrimitivecreateIcoSphere(r, res)
ofCylinderPrimitivecreateCylinder(r, h, res)
ofConePrimitivecreateCone(r, h, res)

3Dカメラ

openFrameworks TrussC 備考
ofEasyCamEasyCam
cam.begin()cam.begin()同じ
cam.end()cam.end()同じ

ライティング・マテリアル

openFrameworks TrussC 備考
ofEnableLighting()enableLighting()
ofDisableLighting()disableLighting()
ofLightLight
light.setDirectional(dir)light.setDirectional(dir)
light.setPointLight()light.setPoint(pos)
light.setAmbientColor(c)light.setAmbient(c)
light.setDiffuseColor(c)light.setDiffuse(c)
light.setSpecularColor(c)light.setSpecular(c)
ofMaterialMaterial
-Material::gold()プリセット
-Material::silver()プリセット
-Material::plastic(color)プリセット

メッシュ(Mesh)

openFrameworks TrussC 備考
ofMeshMesh
mesh.addVertex(v)mesh.addVertex(v)
mesh.addColor(c)mesh.addColor(c)
mesh.addNormal(n)mesh.addNormal(n)
mesh.addIndex(i)mesh.addIndex(i)
mesh.draw()mesh.draw()
mesh.drawWireframe()mesh.drawWireframe()

FBO

openFrameworks TrussC 備考
ofFboFbo
fbo.allocate(w, h)fbo.allocate(w, h)
fbo.begin()fbo.begin()
fbo.end()fbo.end()
fbo.draw(x, y)fbo.draw(x, y)

シェーダー(Shader)

openFrameworks TrussC 備考
ofShaderShader
shader.load(vert, frag)shader.load(vert, frag)
shader.begin()shader.begin()
shader.end()shader.end()
shader.setUniform*()shader.setUniform*()

サウンド

openFrameworks TrussC 備考
ofSoundPlayerSound
sound.load("file.wav")sound.load("file.wav")
sound.play()sound.play()
sound.stop()sound.stop()
sound.setVolume(v)sound.setVolume(v)
sound.setLoop(true)sound.setLoop(true)
ofSoundStreamSoundStreamマイク入力

ビデオ

openFrameworks TrussC 備考
ofVideoGrabberVideoGrabber
grabber.setup(w, h)grabber.setup(w, h)
grabber.update()grabber.update()
grabber.draw(x, y)grabber.draw(x, y)
grabber.isFrameNew()grabber.isFrameNew()

入出力

openFrameworks TrussC 備考
ofSystemLoadDialog()systemLoadDialog()
ofSystemSaveDialog()systemSaveDialog()
ofToDataPath("file")getDataPath() + "file"
ofLoadJson(path)loadJson(path)nlohmann/json
ofSaveJson(path, json)saveJson(path, json)
-loadXml(path)pugixml
-saveXml(path, xml)

ネットワーク

openFrameworks TrussC 備考
ofxTCPClientTcpClient
ofxTCPServerTcpServer
ofxUDPManagerUdpSocket

GUI

openFrameworks TrussC 備考
ofxGui / ofxImGuiDear ImGui(組み込み)imgui::Begin() 等

シーングラフ

openFrameworks TrussC 備考
ofNodeNodeshared_ptrベース
node.setPosition(x, y, z)node->setPosition(x, y, z)
node.setParent(parent)parent->addChild(child)
-RectNode2D UI用、ヒットテスト対応

イベント

openFrameworks TrussC 備考
ofEvent<T>Event<T>
ofAddListener(...)EventListenerRAII形式

ログ

openFrameworks TrussC 備考
ofLog()tcLogNotice()
ofLogVerbose()tcLogVerbose()
ofLogWarning()tcLogWarning()
ofLogError()tcLogError()

スレッド

openFrameworks TrussC 備考
ofThreadThread
-ThreadChannelスレッドセーフなキュー

シリアル通信

openFrameworks TrussC 備考
ofSerialSerial

タイマー

openFrameworks TrussC 備考
-node->callAfter(sec, func)遅延実行
-node->callEvery(sec, func)繰り返し実行

さあ、始めよう

oFで培った経験は、そのまま活きる。