2017-06-22 72 views
0

我已成立了一個不大不小的反射向量模擬器在這裏:https://jsfiddle.net/ahvonenj/1re5n8jg/不工作的反思矢量計算正確

我使用Vectorious我的矢量計算和對象。

程序樣的作品:enter image description here

我從對鼠標光標的畫布中間鑄造射線。我可以成功檢測與牆壁和牆上交點(紅點)的交點。我也能夠得到牆的中間點(藍點)。我想,當我正常化中點矢量時,這是牆的法線。

這裏是聽鼠標移動,投射射線,得到交點並試圖計算反射向量的部分(我已經添加了關於反射向量的實際計算和我認爲我正在計算的一些註釋) :

Global.$canvas.addEventListener('mousemove', function(e) 
 
{ 
 
\t var ctx = Global.ctx; 
 

 
\t var rect = canvas.getBoundingClientRect(); 
 
\t Global.Mouse = new Vector([e.clientX - rect.left, e.clientY - rect.top]); 
 
\t 
 
\t var v1 = Vector.subtract(Global.Mouse, Global.Canvas.Center).normalize(); 
 
\t var mag = Vector.subtract(Global.Canvas.Center, Global.Mouse).magnitude(); 
 
\t var ray = Vector.scale(v1, mag * 3).add(Global.Canvas.Center); 
 
\t 
 
\t ctx.clearRect(0, 0, 600, 600); 
 
\t ctx.beginPath(); 
 
\t 
 
\t for(var i = 0; i < Global.Canvas.Walls.length; i++) 
 
\t { 
 
\t \t var wall = Global.Canvas.Walls[i]; 
 
\t \t 
 
\t \t if(rayIntersectsWith(wall, [Global.Canvas.Center, ray])) 
 
\t \t { 
 
\t \t \t // x_1' - x_0 = v - 2(v dot ñ)ñ 
 
\t \t \t // Where ñ = Normal of the wall 
 
\t \t \t // and v = Vector from center to the point of intersection with the wall 
 
\t \t \t // http://mathworld.wolfram.com/Reflection.html 
 
\t \t 
 
\t \t \t // This is the point on wall where the intersection happens 
 
\t \t \t var point = rayIntersectionPoint(wall, [Global.Canvas.Center, ray]) 
 
\t \t \t 
 
\t \t \t // This is the full ray cast from center towards the mouse 
 
\t \t \t var d = ray; 
 
\t \t \t 
 
\t \t \t // This (probably) is the vector from center to the intersection point on the wall 
 
\t \t \t var v = Vector.subtract(point, Global.Canvas.Center); 
 
\t \t \t 
 
\t \t \t // This represents the wall vector, or a middle of the wall (blue dot on wall) 
 
\t \t \t var wallVector = Vector.add(wall[0], wall[1]).scale(0.5); 
 
\t \t \t 
 
\t \t \t // This is supposed to be the normal of the wall 
 
\t \t \t var wallNormal = Vector.normalize(wallVector); 
 
\t \t \t 
 
\t \t \t // This is supposed to be the 2(v dot ñ) part of the equation 
 
\t \t \t var v_dot_n = Vector.dot(v, wallNormal) * 2; 
 
\t \t \t 
 
\t \t \t // This is supposed to be the v_dot_n * ñ of the equation 
 
\t \t \t var v_dot_n_scaled_by_n = Vector.scale(wallNormal, v_dot_n); 
 
\t \t \t 
 
\t \t \t // This is supposed to be the v - v_dot_n_scale_by_n part of the equation 
 
\t \t \t var dot_vector = Vector.subtract(v, v_dot_n_scaled_by_n); 
 
\t \t \t 
 
\t \t \t console.log('w1', wall[0].x, wall[0].y, ", w2", wall[1].x, wall[1].y) 
 
\t \t \t 
 
\t \t \t var bounceVector = dot_vector 
 

 
\t \t \t console.log(wallVector.x, wallVector.y, wallVector.magnitude()) \t \t \t 
 
\t \t \t console.log(wallNormal.x, wallNormal.y, wallNormal.magnitude()) 
 

 

 
\t \t \t ctx.beginPath(); 
 
\t \t \t ctx.arc(wallVector.x, wallVector.y, Global.isecRadius, 0, 2 * Math.PI, false); 
 
\t \t \t ctx.fillStyle = 'blue'; 
 
\t \t \t ctx.fill(); 
 
\t \t \t ctx.lineWidth = 0; 
 
\t \t \t ctx.strokeStyle = 'blue'; 
 
\t \t \t 
 
\t \t \t ctx.beginPath(); 
 
\t \t \t ctx.arc(dot_vector.x, dot_vector.y, Global.isecRadius * 1.5, 0, 2 * Math.PI, false); 
 
\t \t \t ctx.fillStyle = 'blue'; 
 
\t \t \t ctx.fill(); 
 
\t \t \t ctx.lineWidth = 0; 
 
\t \t \t ctx.strokeStyle = 'blue'; 
 

 
\t \t \t ctx.beginPath(); 
 
\t \t \t ctx.lineWidth = 3; 
 
\t \t \t ctx.strokeStyle = '#00FF00'; 
 
\t \t \t ctx.moveTo(wall[0].x, wall[0].y); 
 
\t \t \t ctx.lineTo(wall[1].x, wall[1].y); 
 
\t \t \t ctx.stroke(); 
 

 

 
\t \t \t console.log(bounceVector.x, bounceVector.y) 
 

 
\t \t \t ctx.beginPath(); 
 
\t \t \t ctx.arc(bounceVector.x, bounceVector.y, Global.isecRadius, 0, 2 * Math.PI, false); 
 
\t \t \t ctx.fillStyle = 'red'; 
 
\t \t \t ctx.fill(); 
 
\t \t \t ctx.lineWidth = 0; 
 
\t \t \t ctx.strokeStyle = 'red'; 
 

 
\t \t \t ctx.beginPath(); 
 
\t \t \t ctx.lineWidth = 1; 
 
\t \t \t ctx.strokeStyle = '#000000'; 
 
\t \t \t ctx.moveTo(point.x, point.y); 
 
\t \t \t ctx.lineTo(bounceVector.x, bounceVector.y); 
 
\t \t \t ctx.stroke(); 
 

 
\t \t \t ctx.beginPath(); 
 
\t \t \t ctx.arc(point.x, point.y, Global.isecRadius, 0, 2 * Math.PI, false); 
 
\t \t \t ctx.fillStyle = 'red'; 
 
\t \t \t ctx.fill(); 
 
\t \t \t ctx.lineWidth = 0; 
 
\t \t \t ctx.strokeStyle = 'red'; 
 
\t \t } 
 
\t } 
 
\t 
 
\t ctx.stroke(); 
 
\t 
 
\t ctx.beginPath(); 
 
\t ctx.lineWidth = 1; 
 
\t ctx.strokeStyle = '#000000'; 
 
    ctx.moveTo(Global.Canvas.Center.x, Global.Canvas.Center.y); 
 
    ctx.lineTo(ray.x, ray.y); 
 
\t ctx.stroke(); 
 
});

我的計算是基於這裏找到方程:http://mathworld.wolfram.com/Reflection.html

但是如果你試圖日你會注意到反射計算幾乎不能用於傾斜牆,目前根本不能用於外牆,所以這是我需要幫助的地方。

的計算公式如下:

x_1'- x_0 = v - 2(v·ñ)ñ. 

凡x_1' - X_0是從牆上的交點反射向量到以往任何時候都應該指向。 v可能與v的相同長度

v是從x_1到牆的交點的向量,所以在我的代碼中它被命名爲v並從中心到牆相交。

ñ是牆的正常。

其餘的方程也應該在我的代碼和我希望相應命名的變量中註釋。

我對這個等式中從v減去的東西有點困惑。 v dot - 返回一個標量,然後乘以2.但是 - 是一個向量,所以2(v dot - )必須意味着標量向量ñ由標量值2(v dotñ)?

最佳猜測我已經能夠從調試這個事情得出結論,牆壁正常是最有可能注意正確計算。

+0

*「我認爲,當我正常化中點矢量時,這是牆的法線。」*不,它不是。我知道矢量,但我不知道JavaScript;如果你能告訴我如何旋轉一個向量90度,或者使用X和Y分量構造一個向量,我可以給你構造法線的代碼。 – Beta

回答

0

從我自己的Geom庫中獲得。

// v1, v2 are Vec 
// reflected vec for line hitting this 
// argument line is the line to be reflected 
//   retVec is the returned resulting vector. 
reflectAsVec : function(line, retVec = new Vec()){ // returns a vector... 
    v2.x = this.p2.x - this.p1.x; 
    v2.y = this.p2.y - this.p1.y; 
    v1.x = line.p2.x - line.p1.x; 
    v1.y = line.p2.y - line.p1.y; 
    var len = v1.dot(v2.norm()) * 2; 
    retVec.x = v2.x * len - v1.x; 
    retVec.y = v2.y * len - v1.y; 
    return retVec; 
}, 

this是具有兩個點P1的直線,P2限定的端部。請注意,v2在計算反射vec的最後兩行進行了歸一化處理。

功能v2.norm() A VEC轉換爲歸一化的向量如下

// u is a number 
norm : function(){ // normalises this to be a unit length. 
    u = Math.hypot(this.x,this.y); 
    this.x /= u; 
    this.y /= u; 
    return this; // returns this 
}, 

而對於v1.dot(vec)

dot : function(vec){ // get the dot product of this and {avec} 
    return this.x * vec.x + this.y * vec.y; // returns number 
}, 

一旦你的反射矢量可以創建從攔截點的反射線和反射的向量。

+0

感謝您的回覆!有趣的是,這個解決方案導致完全相同的情況,當移植到我的jsfiddle:https://jsfiddle.net/ahvonenj/n5twygxr/它的作品...但不像人會期望它的工作,嗯... – Piwwoli

+0

我在想,也許這是奇怪的座標系統,其中(0,0)基本上是左上角,但不應該向量表現正確無論基地...或者我應該嘗試添加像(300,300)或(0,600)爲每個矢量 – Piwwoli

+0

@Piwwoli是座標系不應該。你有統一的尺度?但是,我會檢查我的代碼,直到有一個錯字。 – Blindman67