SVGでのアフィン変換の活用
Canvasによる3Dテクスチャマッピングとパフォーマンスチューニング|最速チュパカブラ研究会
では、HTML5のCanvasの上で、3Dモデルのテクスチャマッピングを行う方法を紹介している。
内容は「アフィン変換とクリッピングを使って、画像上の三角形領域を、別の三角形にマッピングする」というもの。
図を使って説明する方がわかりやすい。
↑画像の上に青い三角形がある。この領域を緑色の三角形にマッピングしたい。
↑青い三角形の中身を緑色の三角形の内部にマッピングした結果。
結果の図から、何をしたいか理解できるだろう。
このような画像の切り取りと変形ができると、3DCGで使われるテクスチャマッピングが2Dグラフィックスで実現できる。
でも、青い三角形と緑の三角形は、大きさ・形が違うので、単純なコピーではうまくいかない。
青い三角形の各頂点が緑の三角形の頂点位置に来て、なおかつ内部の画像が適切に補間されて欲しい。
これは、青の三角形に、適切なアフィン変換を施すことで実現できる。
「Canvasによる3Dテクスチャマッピングとパフォーマンスチューニング|最速チュパカブラ研究会」
では、このアフィン変換に用いる行列を求める方法が説明されている。
アフィン変換は、回転・スケール変換・スキューを行う2x2の行列(4変数)と平行移動ベクトル(2変数)の組み合わせの演算で行われる。
つまり、6つの変数によって1つのアフィン変換が定まる。
入力として2つの三角形が与えられるので、2次元座標を持つ3つの点の位置関係が分かる。
その結果2x3=6つの式が立つので、ある三角形を別の三角形に移すようなアフィン変換は1つに定まる。
上記リンク先の記事では、これをHTML5のCanvasで実現する方法を紹介してあって、興味深く思ったので、勉強を兼ねて同じことをSVGで行ってみた。
以下、その記録。
■ 画像の配置
画像の配置は<image>タグを使う。
<image x='0' y='0' width='256' height='256' xlink:href='checkerboard.png' />
SVGファイル全体
<?xml version='1.0' encoding='UTF-8' standalone='yes'?> <svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' > <image x='0' y='0' width='256' height='256' xlink:href='checkerboard.png' /> </svg>
■ 三角形の描画
三角形(多角形)の描画には<polygon>タグを使う。
<polygon points='150, 150 150, 220 220, 200' stroke='blue' fill='none' stroke-width='2' /> <polygon points='300, 80 360,160 410, 120' stroke='green' fill='none' stroke-width='2' />
SVGファイル全体
<?xml version='1.0' encoding='UTF-8' standalone='yes'?> <svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' > <image x='0' y='0' width='256' height='256' xlink:href="checkerboard.png" /> <polygon points='150, 150 150, 220 220, 200' stroke='blue' fill='none' stroke-width='2' /> <polygon points='300, 80 360,160 410, 120' stroke='green' fill='none' stroke-width='2' /> </svg>
■ symbolとuseを使った複製
同じ画像を複数回使う場合は、その都度ファイルを読み込むのではなく、<polygon>タグを使ってシンボルとして登録し、
<use>タグで再利用するのがよい
image オブジェクトの symbol 登録は次のように行う。 symbol は後から参照できるように id を設定しておく。
<symbol id='img01' viewBox='0 0 256 256'> <image x='0' y='0' width='256' height='256' xlink:href='checkerboard.png' /> </symbol>
use タグを使った symbol の参照は次のように行う。xlink:href で、symbolのidを指定する
<use x='0' y='0' width='256' height='256' xlink:href='#img01' />
異なる場所に配置するには、transform の指定を行う。translate(300,100) で、横に300, 下に100だけ平行移動できる。
<use x='0' y='0' width='256' height='256' xlink:href='#img01' transform='translate(300,100)' />
SVGファイル全体
<?xml version='1.0' encoding='UTF-8' standalone='yes'?> <svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' > <symbol id='img01' viewBox='0 0 256 256'> <image x='0' y='0' width='256' height='256' xlink:href='checkerboard.png' /> </symbol> <use x='0' y='0' width='256' height='256' xlink:href='#img01' /> <use x='0' y='0' width='256' height='256' xlink:href='#img01' transform='translate(300,100)' /> </svg>
■ アフィン変換の適用
画像のアフィン変換は、transform 要素に matrix(a, b, c, d, e, f) を指定して実現する。
「Canvasによる3Dテクスチャマッピングとパフォーマンスチューニング|最速チュパカブラ研究会」で紹介されている方法で、アフィン変換の6変数を計算する。
<use x='0' y='0' width='256' height='256' xlink:href='#img01' transform='matrix(0.959184 -0.244898 0.857143 1.142857 27.551020 -54.693878)' />
SVGファイル全体
<?xml version='1.0' encoding='UTF-8' standalone='yes'?> <svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' > <symbol id='img01' viewBox='0 0 256 256'> <image x='0' y='0' width='256' height='256' xlink:href='checkerboard.png' /> </symbol> <use x='0' y='0' width='256' height='256' xlink:href='#img01' /> <use x='0' y='0' width='256' height='256' xlink:href='#img01' transform='matrix(0.959184 -0.244898 0.857143 1.142857 27.551020 -54.693878)' /> <polygon points='150, 150 150, 220 220, 200' stroke='blue' fill='none' stroke-width='2' /> <polygon points='300, 80 360,160 410, 120' stroke='green' fill='none' stroke-width='2' /> </svg>
■ クリッピング
画像の一部分だけを表示するにはクリッピングを行う。
クリッピング領域の定義は<clipPath>タグを使う。今回は三角形なので、clipPathにpolygonを使う。
後で参照できるように、このクリッピングにidを付けて、<defs>タグで囲む。
<defs> <clipPath id='clip1'> <polygon points='150, 150 150, 220 220, 200' /> </clipPath> </defs>
ここで定義したクリッピングを画像に適用するには、clip-path 要素を追加し、先ほど定義したidを指定する。
<use x='0' y='0' width='256' height='256' xlink:href='#img01' transform='matrix(0.959184 -0.244898 0.857143 1.142857 27.551020 -54.693878)' clip-path='url(#clip1)' />
SVGファイル全体
<?xml version='1.0' encoding='UTF-8' standalone='yes'?> <svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' > <symbol id='img01' viewBox='0 0 256 256'> <image x='0' y='0' width='256' height='256' xlink:href='checkerboard.png' /> </symbol> <use x='0' y='0' width='256' height='256' xlink:href='#img01' /> <defs> <clipPath id='clip1'> <polygon points='150, 150 150, 220 220, 200' /> </clipPath> </defs> <use x='0' y='0' width='256' height='256' xlink:href='#img01' transform='matrix(0.959184 -0.244898 0.857143 1.142857 27.551020 -54.693878)' clip-path='url(#clip1)' /> <polygon points='150, 150 150, 220 220, 200' stroke='blue' fill='none' stroke-width='2' /> <polygon points='300, 80 360,160 410, 120' stroke='green' fill='none' stroke-width='2' /> </svg>
関連エントリ
・アフィン変換とは - 大人になってからの再学習
- 作者: Eric Lengyel,狩野智英
- 出版社/メーカー: ボーンデジタル
- 発売日: 2002/10/25
- メディア: 単行本(ソフトカバー)
- 購入: 7人 クリック: 293回
- この商品を含むブログ (49件) を見る
- 作者: 平岡和幸,堀玄
- 出版社/メーカー: オーム社
- 発売日: 2004/10/01
- メディア: 単行本
- 購入: 27人 クリック: 278回
- この商品を含むブログ (90件) を見る