Created
February 8, 2013 09:01
-
-
Save edom18/4737569 to your computer and use it in GitHub Desktop.
テクスチャマッピングのテスト
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#テクスチャマッピングのテスト | |
Refer to: [2009-02-11 - 最速チュパカブラ研究会](http://d.hatena.ne.jp/gyuque/20090211#1234364019) | |
--- | |
少しだけメッシュ作成、操作部分を最適化。 | |
画像を分割する場合は頂点を結ぶ順番は固定になるため、 | |
頂点のインデックスは特になし。 | |
頂点の数を増やすとだいぶ重いので、 | |
もっとこうしたほうがいいよってのがあったら教えて下さい( ;?Д`) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
html, body, div, p { | |
margin: 0; | |
padding: 0; | |
} | |
canvas { | |
border: solid 1px #333; | |
} | |
#container { | |
width: 500px; | |
position: relative; | |
margin: 15px; | |
} | |
#container p { | |
text-align: center; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="container"> | |
<canvas id="cv" width="500" height="400"></canvas> | |
<p><input type="button" id="btn" value="ゆらゆら" /></p> | |
<!-- /#container --></div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
do (win = window, doc = window.document) -> | |
$ = (selector) -> doc.querySelector selector | |
$$ = (selector) -> doc.querySelectorAll selector | |
w = 0 | |
h = 0 | |
cw = 0 | |
ch = 0 | |
cv = null | |
ctx = null | |
btn = null | |
img = null | |
mm = null | |
mesh = 15 | |
meshes = [] | |
vertexes = [] | |
# --------------------------------------------------------- | |
class Vec3 | |
constructor: (@x = 0, @y = 0, @z = 0) -> | |
zero: -> | |
@x = @y = @z = 0; | |
sub: (v) -> | |
@x -= v.x | |
@y -= v.y | |
@z -= v.z | |
return @ | |
add: (v) -> | |
@x += v.x | |
@y += v.y | |
@z += v.z | |
return @ | |
copyFrom: (v) -> | |
@x = v.x | |
@y = v.y | |
@z = v.z | |
return @ | |
norm: -> | |
Math.sqrt(@x * @x + @y * @y + @z * @z) | |
normalize: -> | |
nrm = @norm() | |
if nrm isnt 0 | |
@x /= nrm | |
@y /= nrm | |
@z /= nrm | |
return @ | |
#scalar multiplication | |
smul: (k) -> | |
@x *= k | |
@y *= k | |
@z *= k | |
return @ | |
#dot product | |
dpWith: (v) -> | |
@x * v.x + @y * v.y + @z * v.z | |
#cross product | |
cp: (v, w) -> | |
@x = (w.y * v.z) - (w.z * v.y) | |
@y = (w.z * v.x) - (w.x * v.z) | |
@z = (w.x * v.y) - (w.y * v.x) | |
return @ | |
toString: -> | |
"#{@x},#{@y},#{@z}" | |
class M44 | |
constructor: (cpy)-> | |
if cpy? | |
@copyFrom(cpy) | |
else | |
@ident() | |
ident: -> | |
@_12 = @_13 = @_14 = 0 | |
@_21 = @_23 = @_24 = 0 | |
@_31 = @_32 = @_34 = 0 | |
@_41 = @_42 = @_43 = 0 | |
@_11 = @_22 = @_33 = @_44 = 1 | |
return @ | |
copyFrom: (m) -> | |
@_11 = m._11 | |
@_12 = m._12 | |
@_13 = m._13 | |
@_14 = m._14 | |
@_21 = m._21 | |
@_22 = m._22 | |
@_23 = m._23 | |
@_24 = m._24 | |
@_31 = m._31 | |
@_32 = m._32 | |
@_33 = m._33 | |
@_34 = m._34 | |
@_41 = m._41 | |
@_42 = m._42 | |
@_43 = m._43 | |
@_44 = m._44 | |
return @ | |
transVec3: (out, x, y, z) -> | |
out[0] = x * @_11 + y * @_21 + z * @_31 + @_41 | |
out[1] = x * @_12 + y * @_22 + z * @_32 + @_42 | |
out[2] = x * @_13 + y * @_23 + z * @_33 + @_43 | |
out[3] = x * @_14 + y * @_24 + z * @_34 + @_44 | |
perspectiveLH: (vw, vh, z_near, z_far) -> | |
@_11 = 2.0 * z_near / vw | |
@_12 = 0 | |
@_13 = 0 | |
@_14 = 0 | |
@_21 = 0 | |
@_22 = 2 * z_near / vh | |
@_23 = 0 | |
@_24 = 0 | |
@_31 = 0 | |
@_32 = 0 | |
@_33 = z_far / (z_far - z_near) | |
@_34 = 0 | |
@_41 = 0 | |
@_42 = 0 | |
@_43 = z_near * z_far / (z_near - z_far) | |
@_44 = 0 | |
#multiplication | |
mul: (A, B) -> | |
@_11 = A._11 * B._11 + A._12 * B._21 + A._13 * B._31 + A._14 * B._41 | |
@_12 = A._11 * B._12 + A._12 * B._22 + A._13 * B._32 + A._14 * B._42 | |
@_13 = A._11 * B._13 + A._12 * B._23 + A._13 * B._33 + A._14 * B._43 | |
@_14 = A._11 * B._14 + A._12 * B._24 + A._13 * B._34 + A._14 * B._44 | |
@_21 = A._21 * B._11 + A._22 * B._21 + A._23 * B._31 + A._24 * B._41 | |
@_22 = A._21 * B._12 + A._22 * B._22 + A._23 * B._32 + A._24 * B._42 | |
@_23 = A._21 * B._13 + A._22 * B._23 + A._23 * B._33 + A._24 * B._43 | |
@_24 = A._21 * B._14 + A._22 * B._24 + A._23 * B._34 + A._24 * B._44 | |
@_31 = A._31 * B._11 + A._32 * B._21 + A._33 * B._31 + A._34 * B._41 | |
@_32 = A._31 * B._12 + A._32 * B._22 + A._33 * B._32 + A._34 * B._42 | |
@_33 = A._31 * B._13 + A._32 * B._23 + A._33 * B._33 + A._34 * B._43 | |
@_34 = A._31 * B._14 + A._32 * B._24 + A._33 * B._34 + A._34 * B._44 | |
@_41 = A._41 * B._11 + A._42 * B._21 + A._43 * B._31 + A._44 * B._41 | |
@_42 = A._41 * B._12 + A._42 * B._22 + A._43 * B._32 + A._44 * B._42 | |
@_43 = A._41 * B._13 + A._42 * B._23 + A._43 * B._33 + A._44 * B._43 | |
@_44 = A._41 * B._14 + A._42 * B._24 + A._43 * B._34 + A._44 * B._44 | |
return @ | |
translate: (x, y, z) -> | |
@_11 = 1; @_12 = 0; @_13 = 0; @_14 = 0; | |
@_21 = 0; @_22 = 1; @_23 = 0; @_24 = 0; | |
@_31 = 0; @_32 = 0; @_33 = 1; @_34 = 0; | |
@_41 = x; @_42 = y; @_43 = z; @_44 = 1; | |
return @ | |
rotX: (r) -> | |
@_22 = Math.cos(r) | |
@_23 = Math.sin(r) | |
@_32 = -@_23 | |
@_33 = @_22 | |
@_12 = @_13 = @_14 = @_21 = @_24 = @_31 = @_34 = @_41 = @_42 = @_43 = 0 | |
@_11 = @_44 = 1 | |
return @ | |
rotY: (r) -> | |
@_11 = Math.cos(r) | |
@_13 = Math.sin(r) | |
@_31 = -@_13 | |
@_33 = @_11 | |
@_12 = @_14 = @_21 = @_23 = @_24 = @_32 = @_34 = @_41 = @_42 = @_43 = 0 | |
@_22 = @_44 = 1 | |
return @ | |
class M22 | |
constructor: -> | |
@_11 = 1 | |
@_12 = 0 | |
@_21 = 0 | |
@_22 = 1 | |
getInvert: -> | |
out = new M22 | |
det = @_11 * @_22 - @_12 * @_21 | |
if 0.0001 > det > -0.0001 | |
return null | |
out._11 = @_22 / det | |
out._22 = @_11 / det | |
out._12 = @_12 / det | |
out._21 = @_21 / det | |
return out | |
class MeshMgr | |
constructor: (@g, @img, @mesh) -> | |
@vertex = [] | |
addVertex: (x, y, ux, uy, corner) -> | |
@vertex.push(new Vertex x, y, ux, uy, corner); | |
addIndex: (x, y) -> | |
@index.push(x, y); | |
getMesh: -> | |
return @vertex | |
class Vertex | |
constructor: (@x, @y, @ux, @uy, @corner) -> | |
@ox = x | |
@oy = y | |
# --------------------------------------------------------- | |
drawTriangle = (g, img, vertex_list, uv_list) -> | |
_Ax = vertex_list[2] - vertex_list[0] #x of vector 1 | |
_Ay = vertex_list[3] - vertex_list[1] #y of vertor 1 | |
_Bx = vertex_list[4] - vertex_list[0] #x of vector 2 | |
_By = vertex_list[5] - vertex_list[1] #y of vector 2 | |
Ax = (uv_list[2] - uv_list[0]) * img.width | |
Ay = (uv_list[3] - uv_list[1]) * img.height | |
Bx = (uv_list[4] - uv_list[0]) * img.width | |
By = (uv_list[5] - uv_list[1]) * img.height | |
# move position from A(Ax, Ay) to _A(_Ax, _Ay) | |
# move position from B(Ax, Ay) to _B(_Bx', _By) | |
# A,Bのベクトルを、_A,_Bのベクトルに変換することが目的。 | |
# 変換を達成するには、a, b, c, dそれぞれの係数を導き出す必要がある。 | |
# | |
# ↓まずは公式。アフィン変換の移動以外を考える。 | |
# | |
# _Ax = a * Ax + c * Ay | |
# _Ay = b * Ax + d * Ay | |
# _Bx = a * Bx + c * By | |
# _By = b * Bx + d * By | |
# | |
# ↓上記の公式を行列の計算で表すと以下に。 | |
# | |
# |_Ax| = |Ax Ay||a| | |
# |_Bx| = |Bx By||c| | |
# | |
# ↓a, cについて求めたいのだから、左に掛けているものを「1」にする必要がある。 | |
# 行列を1にするには、逆行列を左から掛ければいいので、両辺に逆行列を掛ける。(^-1は逆行列の意味) | |
# | |
# |Ax Ay|^-1 |_Ax| = |a| | |
# |Bx By| |_Bx| = |c| | |
# | |
# この式をプログラムで表すと以下になる。 | |
m = new M22 | |
m._11 = Ax | |
m._12 = Ay | |
m._21 = Bx | |
m._22 = By | |
mi = m.getInvert() #To invert | |
if mi is null then return | |
a = mi._11 * _Ax + mi._12 * _Bx | |
c = mi._21 * _Ax + mi._22 * _Bx | |
b = mi._11 * _Ay + mi._12 * _By | |
d = mi._21 * _Ay + mi._22 * _By | |
tx = vertex_list[0] - (a * uv_list[0] * img.width + c * uv_list[1] * img.height) | |
ty = vertex_list[1] - (b * uv_list[0] * img.width + d * uv_list[1] * img.height) | |
g.save() | |
g.strokeStyle = '#f00' | |
g.beginPath() | |
g.moveTo vertex_list[0], vertex_list[1] | |
g.lineTo vertex_list[2], vertex_list[3] | |
g.lineTo vertex_list[4], vertex_list[5] | |
#for debugging | |
g.stroke() | |
g.clip() | |
g.closePath() | |
g.transform a, b, c, d, tx, ty | |
g.drawImage img, 0, 0 | |
g.restore() | |
# --------------------------------------------------------- | |
getVertex = (ctx, img) -> | |
mm = new MeshMgr ctx, img, mesh | |
w = img.width | |
h = img.height | |
wi = w / mesh | |
hi = h / mesh | |
_x = 0 | |
_y = 0 | |
len = mesh * mesh + mesh * 2 + 1 | |
ret = [] | |
for i in [0...len] | |
x = wi * _x | |
y = hi * _y | |
if x >= w | |
_x = 0 | |
_y++ | |
corner = true | |
else | |
_x++ | |
corner = false | |
if y >= h | |
corner = true | |
ux = x / w | |
uy = y / h | |
mm.addVertex(x, y, ux, uy, corner) | |
# --------------------------------------------------------- | |
deg = 180 | |
PI = Math.PI | |
TO_RAD = PI / 180 | |
cos = Math.cos | |
sin = Math.sin | |
draw = -> | |
#[arguments list] | |
#transform(a, b, c, d, tx, ty) | |
# ↓ as result. | |
#|a c tx| |x| = ax + cy + tx | |
#|b d ty|x|y| = bx + dy + ty | |
#|0 0 1 | |1| = 0 + 0 + 1 | |
ctx.clearRect -50, -50, cw, ch | |
meshes = mm.getMesh() | |
seg = mesh + 1 | |
step = 360 / mesh | |
l = meshes.length - 1 | |
while (l > 0) | |
i = 0 | |
l -= mesh | |
deg++ | |
#deg += mesh * i | |
while (i < mesh) | |
i++ | |
m = meshes[l + i] | |
k = ~~(cos((deg * step) * TO_RAD) * 10) | |
m.x = m.ox + k | |
deg = deg % 180 | |
for m, i in meshes | |
if m.corner is true | |
continue | |
v1 = meshes[i + 0] | |
v2 = meshes[i + 1] | |
v3 = meshes[i + seg + 0] | |
v4 = meshes[i + seg + 1] | |
drawTriangle ctx, img, [v1.x, v1.y, v2.x, v2.y, v3.x, v3.y], [v1.ux, v1.uy, v2.ux, v2.uy, v3.ux, v3.uy] | |
drawTriangle ctx, img, [v4.x, v4.y, v3.x, v3.y, v2.x, v2.y], [v4.ux, v4.uy, v3.ux, v3.uy, v2.ux, v2.uy] | |
# --------------------------------------------------------- | |
win.addEventListener 'load', -> | |
cv = $ 'canvas' | |
ctx = cv.getContext '2d' | |
cw = cv.width | |
ch = cv.height | |
btn = $ '#btn' | |
ctx.translate 50, 50 | |
flg = false | |
timer = null | |
btn.addEventListener 'click', -> | |
if (flg = !flg) is true | |
_loop = -> | |
timer = setTimeout -> | |
draw() | |
_loop() | |
, 32 | |
_loop() | |
else | |
clearTimeout timer | |
, false | |
# --------------------------------------------------------- | |
img = new Image() | |
img.onload = -> | |
vertexes = getVertex ctx, img | |
draw() | |
img.src = if doc.domain.indexOf('jsrun.it') > -1 then 'http://jsrun.it/assets/k/G/i/S/kGiSG.jpg' else 'pic.jpg' | |
# --------------------------------------------------------- | |
, false |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment