Open17

フルスクリーンの簡単なお絵かきアプリを作るメモ

SFPGMRSFPGMR

動画を制作するのに

  • フルスクリーンで描ける
  • UIがデフォルトでは表示されず、描画エリアを邪魔しない
  • 背景ビットマップが別レイヤで読み込まれ、ペンタブで描いたストロークで上書きされない

ものを探していたところ、fulldrawを見つけたのだが、少し要件に合わなかった。
ソースコードを改造しようかなと思ったが、APIベースのソースなので画像読み込みとか面倒そうだった。

https://github.com/0mg/fulldraw

SFPGMRSFPGMR

こんな感じのコードになった。

if (!menuOpen) {
	if (MouseL.down()) {
		Stroke s{};
		s.color = penColor;
		s.thickness = thickness;
		PointData start;
		start.pressure = Pentablet::IsAvailable() ? Pentablet::Pressure() : 1.0f;
		start.pos = Cursor::Pos();
		s.strokePoints.push_back(start);
		s.drawing = true;
		strokes.push_back(s);
		currentStroke = strokes.end() - 1;
	}
	else if (MouseL.pressed()) {

		PointData start;
		start.pressure = Pentablet::IsAvailable() ? Pentablet::Pressure() : 1.0f;
		start.pos = Cursor::Pos();
		currentStroke->strokePoints.push_back(start);
	}
	else if (MouseL.up()) {
		currentStroke->drawing = false;
	}
}

しかしちょっとWindowメッセージを直接ハンドルしたものと比べると描画がガタガタするな・・
OpenSiv3Dのイベントループ単位の処理だと、座標データの取りこぼしがあるのかもな。気のせいかもだけど。

SFPGMRSFPGMR

OpenSiv3Dのソースコードをざっと見る限り、イベントループのタイミングでペンのステータスをpeekしてるような。

SFPGMRSFPGMR

ウインドウメッセージだと、OSがキューイングしてくれるので取りこぼしはなさそうだけどね。wintabもその辺考慮はもちろんしてるだろうけど、このAPI知らんからよくわかんないな。

SFPGMRSFPGMR

こんな感じで、OpenSiv3DのPentabで書くとちょっとガタってなるんだよね。
太さはちょっと別にしても、滑らかさが違う。

SFPGMRSFPGMR

OpenSiv3Dでのペンタブのupdate()見ると、やっぱりメッセージループ単位でデータを更新し、その間に得られたデータのうち最新のものをサンプルしてるようだ。
つまり描画フレーム間に動いた軌跡データが欠落するってことのようなんだな。
これが滑らかさの違いになって表れているように思いますな。

https://github.com/Siv3D/OpenSiv3D/blob/main/Siv3D/src/Siv3D-Platform/WindowsDesktop/Siv3D/Pentablet/Pentablet/CPentablet.cpp#L79

SFPGMRSFPGMR

しかしこれはこういう仕様だと割り切っている感じもしますな。

SFPGMRSFPGMR

しかしこのwintabっていうAPIだと筆圧の精度も上げられそうですな。
私が使っているのはかなり安物のペンタブなんだけど、それでも筆圧は8192段階検知できるのですわ。
WM_POINTER_XXX+アルファで得られる筆圧データの精度は1024段階なのでね。

SFPGMRSFPGMR

ここまで作成したコマンドをアンドゥ・リドゥできるようにした。
また、ストローク単位でアンドゥ・リドゥができるようにしてみた。