| 12-05-2007, 11:24 PM | #1 |
I am working on a simple physics system for a map of mine. The entire thing is done, except for bouncing off the ground. If I have a projectile, (knowing its x,y, and z-rates) and the point of ground it is colliding with, how do I find the x,y,and z rates that it should bounce off of, saying that is bounces as high as it fell (1:1 ratio). Please explain everything, because I have absolutely no idea how to do this and I would like to learn, instead of just being given a formula and putting it into my map. |
| 12-06-2007, 02:11 AM | #2 |
You're going to want to know vector math for this, because it makes the whole thing a whole lot simpler to understand. References to get you started: http://en.wikipedia.org/wiki/Coordinate_vector http://en.wikipedia.org/wiki/Dot_product http://en.wikipedia.org/wiki/Cross_product Alright, so here's what you need to do: - Compute the normal vector for the ground where you're hitting. You'll need three (very close) points to do this. You use your three points A,B,C to get the vectors A->B and A->C. The normal is the cross product of those two vectors. - Compute the projection (see dot product article) of your velocity onto the normal vector. - Subtract that projection from your velocity twice. Code:
n1 = P3 - P1 n2 = P2 - P1 n = n1 x n2 (or n2 x n1, one has the right sign) v -= 2*proj(v, n) What did we do here? Essentially, we isolated the velocity going into the ground (the projection onto the normal vector), and flipped it (subtracted it twice). If the ground is perfectly flat, the z speed would have flipped. If the ground was inclined 45 degrees along x, z and x would have swapped. I know that this is probably a confusing explanation. But vector math is really, really useful for physics, so you should get a head start on it now. |
| 12-06-2007, 12:31 PM | #3 |
It occurred to me that I wrote a JASS vector structure in the past. It's a bit old, but you should find it useful. JASS://======================================= // 3-Dimensional Vector Library // Author: Strilanc //======================================= globals constant integer nill = 0 endglobals struct Vector readonly static integer numAllocated = 0 public real x public real y public real z ///Creates a vector with the given coordinates public static method create takes real x, real y, real z returns Vector local Vector v = Vector.allocate() set v.x = x set v.y = y set v.z = z set Vector.numAllocated = Vector.numAllocated + 1 return v endmethod ///Cleans up properly private method onDestroy takes nothing returns nothing set Vector.numAllocated = Vector.numAllocated - 1 endmethod ///Creates a Vector with the same coordinates as the given Vector public method clone takes nothing returns Vector if (this == nill) then return nill endif return Vector.create(this.x, this.y, this.z) endmethod ///Destroys this vector and returns the given vector ///mainly useful for removing temporary values ///EXAMPLE: v = v.destroyAndReturn(v.crossProduct(w)) ///NOTE: be careful using this method!! public method destroyAndReturn takes Vector v returns Vector if (this != nill) then call this.destroy() endif return v endmethod ///Returns a string representation of this vector public method toString takes nothing returns string if (this == nill) then return "Vector:NILL" endif return "Vector:[" + R2S(this.x) + ", " + R2S(this.y) + ", " + R2S(this.z) + "]" endmethod //============================ //===== In-Place Methods ===== //============================ ///Replaces all of this vector's coordinates with the coordinates of the given vector public method paste takes Vector v returns boolean if (this == nill or v == nill) then return false endif set v.x = this.x set v.y = this.y set v.z = this.z return true endmethod ///Sets this vector to the zero vector public method clear takes nothing returns boolean if (this == nill) then return false endif set this.x = 0 set this.y = 0 set this.z = 0 return true endmethod ///Returns this vector's length public method getLength takes nothing returns real if (this == nill) then return 0 endif return SquareRoot(this.x*this.x + this.y*this.y + this.z*this.z) endmethod ///Sets the length of this vector to d public method setLength takes real d returns boolean local real r if (this == nill) then return false endif set r = this.getLength() if (r <= 0) then return (d == 0) //zero vector can't be extended endif set r = d/r set this.x = this.x * r set this.y = this.y * r set this.z = this.z * r return true endmethod ///Adds the given vector scaled by c to this vector public method increaseBy takes Vector v, real c returns boolean if (this == nill or v == nill) then return false endif set this.x = this.x + v.x * c set this.y = this.y + v.y * c set this.z = this.z + v.z * c return true endmethod ///Scales this vector by the given amount public method scaleBy takes real c returns boolean if (this == nill) then return false endif set this.x = this.x * c set this.y = this.y * c set this.z = this.z * c return true endmethod //============================== //========= Arithmetic ========= //============================== ///Returns the dot product of two vectors: the sum of their coordinates multiplied together public static method dot takes Vector v1, Vector v2 returns real if (v1 == nill or v2 == nill) then return 0 endif return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z endmethod ///Returns a vector equal to the cross product of the two given vectors public static method cross takes Vector v1, Vector v2 returns Vector if (v1 == nill or v2 == nill) then return nill endif return Vector.create(v1.y*v2.z-v2.y*v1.z, v1.z*v2.x-v2.z*v1.x, v1.x*v2.y-v2.x*v1.y) endmethod ///Returns a vector equal to the sum of the two given vectors public static method sum takes Vector v1, Vector v2 returns Vector if (v1 == nill or v2 == nill) then return nill endif return Vector.create(v1.x+v2.x, v1.y+v2.y, v1.z+v2.z) endmethod ///Returns the length of this vector public method abs takes nothing returns real return this.getLength() endmethod ///Sets the length of this vector to 1 public method normalize takes nothing returns boolean return this.setLength(1) endmethod //============================== //========= Projection ========= //============================== ///Returns the magnitude of the parts of this vector parallel to the given vector public method scalarProjection takes Vector v returns real local real d if (this == nill or v == nill) then return 0. endif set d = v.getLength() if (d <= 0) then return 0 //v is the zero vector else return Vector.dot(this, v)/d endif endmethod ///Returns the parts of this vector parallel to the given vector public method projection takes Vector v returns Vector local Vector p if (this == nill or v == nill) then return nill endif //the projection is in the direction of v set p = v.clone() //and has a length equal to the scalar projection call p.setLength(this.scalarProjection(v)) return p endmethod ///Returns the parts of this vector not parallel to the given vector public method perp takes Vector v returns Vector local Vector p if (this == nill or v == nill) then return nill endif //subtract the parallel parts set p = this.projection(v) call p.scaleBy(-1) call p.increaseBy(this, 1) return p endmethod endstruct |
