cocoa アプリでデータを一覧で見たいとき、NSTableView が便利そう。
Cell Based と View Based の二つがある。
ここら辺、ワイも慣れてないので、参考記事を参照のほどを。
参考記事
『NSTableView (View Based ) の初歩的実装』
これ。

ウマ娘関連のネタが多いでしょうか
cocoa アプリでデータを一覧で見たいとき、NSTableView が便利そう。
Cell Based と View Based の二つがある。
ここら辺、ワイも慣れてないので、参考記事を参照のほどを。
『NSTableView (View Based ) の初歩的実装』
これ。
このシリーズも今回4回目。
継続していて気が付いたことは、アプリの製作は文法の学習とはまた異なった知識が必要だということ。
前回扱った内容はまさにそれで、メニューイベントを管理するクラスをどこに置くか?という話題で、ある程度凝ったアプリならば、NSWindowController の派生クラスに置くのがいいのでは、みたいな話をした。
答えが複数あり、状況によって最適解を探す、というのは、プログラミングに限らず、習得するのが難しい領域の一つなんでしょうね。
前置きはともかく、今回は、特定のクラスが必要になったとき、それを Objective-C でどう構成するかという話。
どう構成するかはひとまず置いて、定型的な書き方の復習。
@interface Hoge : NSObject
-(nullable instancetype) initHoge;
@end
@implementation Hoge
-(nullable instancetype) initHoge;
{
self = [super init];
if(self)
{
//初期化処理
}
return self;
}
@end
この書き方、昔は無茶苦茶違和感あったけど、最近慣れたな。
なお、initXxx は init family とかイニシャライザなどと言われ、クラスの初期化を受け持つメソッド。
init 以下に適当な文字(列)をつけるが、最初の文字は大文字にする必要がある。
だから、initialize は init familiy ではない。
以前に他人のコードを読んでいたとき、同一クラス内で init と initialize が同居していて「は?」と思ったのだが、そういうことらしい。
(続く)
Metal と OpenGL
OpenGL はネット上で独学できるリソースが転がっているのがいいなあ。
『独学で一ヶ月間 OpenGL を学んで得た基礎知識のまとめ』
このシリーズは、初学者向け。軽快な口調で読みやすい。
Metal はなあ・・・(遠い目)。
某プロジェクトでキモになるのはシェーダーへの頂点データの渡し方。
具体的には、以下の for in ループで以下のように渡している。
for mesh in model.meshes {
let vertexBuffer = mesh.mtkMesh.vertexBuffers[0].buffer
renderEncoder.setVertexBuffer(vertexBuffer, offset: 0,
index: 0)
for submesh in mesh.submeshes {
let mtkSubmesh = submesh.mtkSubmesh
renderEncoder.drawIndexedPrimitives(type: .triangle,
indexCount: mtkSubmesh.indexCount,
indexType: mtkSubmesh.indexType,
indexBuffer: mtkSubmesh.indexBuffer.buffer,
indexBufferOffset: mtkSubmesh.indexBuffer.offset)
}
}
mtkMesh が良い感じに効いていると思うのだが、なんらかの事情でこれが使えない場合はどうするのか???
・・・などと Metal 関係については、たいそう歯切れ悪く書いていたが、現在は、いくらか改善された。
というのはたまたま参加した iOS/MacOS の勉強会で、軽くレクチャーを受けたらこの分野の理解がかなり深まったから。
それまでは、これまで同様、ある程度理解した後に、サンプル作成して理解を深めようと思っていたのだが、こと、この分野に関してはそれでは効率的でないようだ。
画像処理、特に 3DCG の領域では、プログラミング的な能力より、数理的な理論の理解の方が重要なので、理解度が足踏みしていると感じたら、分かっている人に聞くのも一つの手でしょう。
Obj-C と Swift を行ったり来たりする時、気にしておいた方がいいポイント。
・・の前に
世間的には Swift ユーザーの方が多い。しかし、既存プロジェクトは Obj-C で書かれている。
という現状なので、(あるんじゃないかと予想はしていたのだが)やはり Obj-C → Swift 自動変換ツールはあるようです。
こちらの記事などどうぞ。
Swift の良い点の一つが、メソッドのラベルがわかりやすいところ。
Obj-C で
[img drawInRect:rect blendNode:mode alpha:alpha]
と書いていたところが、Swift では
img.draw(in:rect blendNode:mode alpha:alpha)
となる。
Obj-C ではメソッドに第一引数が含まれているから、若干わかりにくい。
ところで Swift 使っていない人ほど見出しのように誤解している。
スクリプト系の言語っぽい雰囲気出してるからかなあ?
単純に使ってないだけ?
実際には、Swift の方が C より変数の型にうるさいです。
このブログでは、けっこう言っているし、実演もしていると思うのだが、ワイは(Swift に限らず)簡単なプログラムをコマンドラインで実行することがよくある。
なので、実行環境の整備の仕方。
Swift の場合は Mac のターミナルや VS code のターミナルから swift -v と打ち込むと
swift -v
Apple Swift version 5.7.2 (swiftlang-5.7.2.135.5 clang-1400.0.29.51)
Target: arm64-apple-macosx13.0
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-help intro
Welcome to Swift!
Subcommands:
swift build Build Swift packages
swift package Create and work on packages
swift run Run a program from a package
swift test Run package tests
swift repl Experiment with Swift code interactively
Use `swift --help` for descriptions of available options and flags.
Use `swift help ` for more information about a subcommand.
と表示される。
(表示されない場合は、コマンドラインツールがインストールされていない、などの不備がある。準備する)
上では swift build コマンドが表示されているが、もっと簡単には swiftc コマンドを使う。
hello.swift
print("hello Swift")
というプログラムがあったとき、swiftc hello.swift を実行すると hello という実行ファイルを作ってくれる。
VS code だとこんな感じになる。

実行できてますね。
Foundation フレームワークと C 標準ライブラリの機能は、特に指示しなくても使えるようです。
なお、ファイルの冒頭に #!/usr/bin/swift を付加してファイル自体に実行権限を与えるとシェルスクリプトっぽく使える。
実際にこの使い方をするかどうかは微妙ですが。
この記事参照。
zip や map も Obj-C では全く出てこない。
この記事参照。
3DCG で頻出の各種行列について、メモ。
・・・するつもりだったのだが、イマドキの API は一度各種行列の形を決めておけば、行列の中身を知らなくても、どうにかこうにかコーディング自体はできそう。
例えば、Metal であれば、以下のコードの vertxIn.position で示されたモデルの各点は(一度、projectionMatrix などを書いておけば)
float4 position = uniforms.projectionMatrix * uniforms.viewMatrix
* uniforms.modelMatrix * vertexIn.position;
の変換で float4 position に移される。
だから、これをシェーダーに書いておけばいい、という寸法だ。
この時、ややこしいとされている uniforms.projectionMatrix の要素を具体的に知らなくても必須パラメータの設定ができていれば、正しく動作する。
まず、最低限、理解すべきは
・M → V → P の流れ
・M に関しては Translation・Rotatio・Scale を意味する行列の積で表現できる
ことなのだろう。
というわけで、これ。
let x = simd_double4(x: 10, y: 20, z: 30, w: 40)
let y = simd_double4(x: 1, y: 2, z: 3, w: 4)
/*
A matrix of two columns and four rows:
10 1
20 2
30 3
40 4
*/
let a = simd_double2x4([x, y]) // columns
/*
A matrix of four columns and two rows:
10 20 30 40
1 2 3 4
*/
let b = simd_double4x2(rows: [x, y])
これを踏まえて、projectionMatrix p を考える。
let y = 1 / tan(fov * 0.5)
let x = y / aspect
let z = lhs ? far / (far - near) : far / (near - far)
let X = float4( x, 0, 0, 0)
let Y = float4( 0, y, 0, 0)
let Z = lhs ? float4( 0, 0, z, 1) : float4( 0, 0, z, -1)
let W = lhs ? float4( 0, 0, z * -near, 0) : float4( 0, 0, z * near, 0)
let p = simd_float4x4([X, Y, Z, W])//columns
でしょうか。
これも小理屈がある。
移動・拡大・回転の行列を translateMatrix, scaleMatrix, rotateMatrix としたとき、viewMatrix は
(translateMatrix * scaleMatrix * rotateMatrix).inverse//inverse 逆行列
でいいらしい。
(続く)