2017-06-22 2 views
0
ne fonctionne pas correctement

je l'ai mis en place une sorte d'un simulateur de vecteur de réflexion ici: https://jsfiddle.net/ahvonenj/1re5n8jg/calcul de vecteur de réflexion

J'utilise Vectorious pour mes calculs vectoriels et des objets.

Le genre de programme de travaux: enter image description here

Je CASTING rayons à partir du milieu de la toile vers le curseur de la souris. Je peux détecter avec succès les intersections de rayons avec les murs et le point de l'intersection sur le mur (points rouges). Je suis également capable d'obtenir le point central du mur (points bleus). Je pense que lorsque je normalise le vecteur du point milieu, c'est la normale du mur. Voici la partie qui écoute le mouvement de la souris, jette le rayon, obtient l'intersection et essaie de calculer les vecteurs de réflexion (j'ai ajouté quelques commentaires concernant les calculs réels pour le vecteur de réflexion et ce que je pense que je calcule) :

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(); 
 
});

Mes calculs sont basés sur les équations trouvées ici: http://mathworld.wolfram.com/Reflection.html

Mais si vous essayez e e fiddle, vous remarquerez que les calculs de réflexion fonctionnent à peine pour le mur incliné et actuellement ne fonctionnent pas du tout pour les murs extérieurs, c'est là que j'ai besoin d'aide.

L'équation ressemble à ceci:

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

Où x_1' - x_0 est le vecteur de réflexion à partir du point d'intersection de la paroi où jamais, il devrait pointer. V est le vecteur de x_1 au point d'intersection du mur, donc dans mon code, il est nommé v et va du centre à l'intersection du mur.

ñ est la normale du mur.

Le reste de l'équation devrait également être commenté dans mon code et les variables nommées en conséquence j'espère.

Je suis un peu confus avec les choses soustraites de v dans l'équation. v dot ñ renvoie un scalaire, qui est ensuite multiplié par 2. Toutefois, ñ est un vecteur donc 2 (v dot ñ) doit signifier scaling vector ñ par la valeur scalaire de 2 (v dot ñ)?

Je suppose que j'ai pu conclure du débogage de cette chose est que la normale de la paroi est probablement la note correctement calculée.

+0

* "JE PENSE que lorsque je normalise le vecteur du point milieu, c'est la normale du mur." * Non, ce n'est pas le cas. Je connais les vecteurs, mais je ne connais pas javascript; Si vous pouvez me dire comment faire pivoter un vecteur de 90 degrés, ou construire un vecteur en utilisant les composants X et Y, je peux vous donner le code qui va construire la normale. – Beta

Répondre

0

De ma propre bibliothèque Geom j'ai.

// 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 est une ligne avec deux points p1, p2 définissant les extrémités. Notez que la v2 est normalisée pour les deux dernières lignes calculant le vec réfléchi.

La fonction v2.norm() convertit un Vec un vecteur normalisé comme suit

// 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 
}, 

Et pour 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 
}, 

Une fois le vecteur réfléchi, vous pouvez créer la ligne réfléchie à partir du point d'interception et le vecteur réfléchi.

+0

Merci pour la réponse! Chose intéressante, cette solution aboutit à exactement la même situation lors de son portage sur mon jsfiddle: https://jsfiddle.net/ahvonenj/n5twygxr/ Cela fonctionne plutôt ... mais pas comme on s'attendrait à ce qu'il fonctionne, hmm ... – Piwwoli

+0

Je pense que c'est peut-être le système de coordonnées bizarre où (0, 0) est fondamentalement le coin supérieur gauche, mais les vecteurs ne devraient pas se comporter correctement quelle que soit la base ... ou peut-être que je devrais essayer d'ajouter (300, 300) ou (0, 600) pour chaque vecteur – Piwwoli

+0

@Piwwoli Oui, le système de coordonnées ne devrait pas avoir d'importance. Avez-vous une échelle uniforme ?? Mais je vais vérifier mon code juste au cas où il y aurait une faute de frappe. – Blindman67