Reflecting a 2d vector by a 2d normal?

BlitzMax Forums/BlitzMax Programming/Reflecting a 2d vector by a 2d normal?

AntonyWells(Posted 2005) [#1]
Anyone got a bit of code/theory that reflects a 2d vector by a 2d normal(Also a vector)?
Or even better, a way to do sliding 2d collisions with blitz's own image collision or pure math?


Warpy(Posted 2005) [#2]
The answer to this and a lot of useful related maths was just discussed a few days ago in http://www.blitzbasic.com/Community/posts.php?topic=52384


AntonyWells(Posted 2005) [#3]
I'm probably missing it, but I can't see anything to do with sliding 2d collisions on there? can you cut and paste the bit in question please?


Warpy(Posted 2005) [#4]
I was talking about the reflecting vectors thing, but good point...

To slide instead of bounce, get the reflected vector, and multiply it by the unit vector pointing along the line.




AntonyWells(Posted 2005) [#5]
Thanks but I can't understand your writing warp :)

Any chance you can put it in the form of a simple bmax function?

type maths
    function reflectVector( vectx#,vecty#,normx#,normy#)
        relx = warpy code.
        rely = warpy code.
    end function
   global relx#,rely#
end type


I'll give you a billion dollers in return.


Warpy(Posted 2005) [#6]
fair enough, my writing's rubbish.
type maths

method reflectVector(vectx#,vecty#,normx#,normy#)
	dotprod#=-vectx*normx-vecty*normy
	relx=vectx+2*normx*dotprod
	rely=vecty+2*normy*dotprod
end method

method slide(vectx#,vecty#,linex#,liney#,normx#,normy#)
       reflectVector(vectx,vecty,normx,normy)
       slidex=relx*linex
       slidey=rely*liney
end method

global relx#,rely#
global slidex#,slidey#

end type


That should work, though who knows these days? :)


AntonyWells(Posted 2005) [#7]
thanks again but there's two undefined variables used in the first func, vx,vy. that a typo and just vectx,y?


Vertex(Posted 2005) [#8]
R = I - 2N(N*I)

Where is
R = Reflected Ray
I = Incident Ray
N = Normal Vector

cu olli


Warpy(Posted 2005) [#9]
yep, it was meant to be vectx/y...
What I've got is the same thing as Vertex, but done in a different order :P


AntonyWells(Posted 2005) [#10]
cool, one more dumb question and we're done. In the slide function, there's..what is the slide function? :) And linex,liney, is the the depth of intersection or the velocity of the intersection?


Warpy(Posted 2005) [#11]
the slide function gives you the velocity if you want it to slide along the line it's colliding with
linex,liney is a unit vector in the direction of the line


Tibit(Posted 2005) [#12]
Don't forget Bounce and friction ;)
method CollisionResponse( Bounce#, Friction# )
rem

  Divide our veclocity vector in two parts. One parallell to our line
  - This is already solved and this vector is called slidex,slidey.
  Multiply these fields with Friction# which should be a value from
  0.0 to 1.0. In this example our friction is = 0.
  The other is the part of the velocity vector projected on the line's
  normal. This is the bounce. Multiply this vector with Bounce#, which
  is a value from 0.0 to 0.9. Where we in this case would want to set it
   = 0 for NO bounce at all - sliding. 

endrem

   bounceX:*Bounce
   bounceY:*Bounce
   slidex:*Friction
   slidey:*Friction
endmethod

  global relx#,rely#
  global slidex#,slidey#
  global bounceX#,bounceY#

end type
Need help getting the line's normal though. Is it as simple as:
LineNormX = LineX
LineNormY = -LineY
I get a strong feeling that is wrong..

Public 2D Physic Library
So now that everyone is working on vector maths and physics shoudn't we start some combined effort to make a public opensource community physics module for 2D?


Warpy(Posted 2005) [#13]
yep, that's wrong.
You can get *a* vector (V1x,V1y) that's perpendicular to a line (linex,liney) by setting V1x = 1, V1y = -linex/liney, but it isn't a unit vector, so you need to divide V1x and V1y by Sqr(1+V1y*V1y). Then add a check for if liney is zero to avoid divide by zero errors, and you're probably set.

Of course, I don't use that method :P
I get:
an#=atan2(liney,linex)
nx#=cos(atan2+90)
ny#=sin(atan2+90)

But that's probably quite slow.


Haramanai(Posted 2005) [#14]
I am with you Wave! Let's make this mod.
I am Making the start...
Here what I have done this morning



Tibit(Posted 2005) [#15]
Thanks Warpy!

Great Haramanai!

I'll start to put together our stuff into an example. And I guess we should start a new topic for this. I'll use my vector library so that we can base everything on vector operations.

I'll write a short project plan too.


AntonyWells(Posted 2005) [#16]
I get the 2d normal by sampling a 20x20 region of the image with the centre being the first pixel that the motion vector collided with.

Method pointNormal(x#,y#,l)
		normx=0
		normy=0
		For Local cx# = -10 To 10
		Local nx# = cx/4.0
		For Local cy# = -10 To 10
			Local ny# = cy/4.0
			Local rx# = x+nx
			Local ry# = y+ny
			Local tx,ty
			tx = rx/twidth
			ty = ry/theight
			Local til:tile = Null
			If tx>-1 And ty>-1 And tx<width And ty<height
				til = map[tx,ty,l]
			End If
			If til<>Null
				Local ox#,oy#
				ox = rx-(tx*twidth)
				oy = ry-(ty*theight)
				normx=normx+nx*til.cmap[ox,oy]
				normy=normy+ny*til.cmap[ox,oy]
			End If
									
		Next
		Next
	'	normx=normx/16
	'	normy=normy/16
		Local mag# = Sqr(normx*normx+normy*normy)
		If mag<0.001 mag=0.001
		normx=normx/mag
		normy=normy/mag
		
		
	End Method


it works well.

It's a shame we can't find my old vertlet lib, we could use it as the basis for a 2d physic lib and do ragdoll etc.


Warpy(Posted 2005) [#17]
holy crunk, that's entirely the wrong way to do it!


AntonyWells(Posted 2005) [#18]
Define wrong when it works?


Warpy(Posted 2005) [#19]
wrong because it's needlessly complicated and slow


AntonyWells(Posted 2005) [#20]
Just needs a 2byte times image size array for each tile and checks can be reduced to a couple of look ups per frame. ultra fast and accurate.