The use of TFormVector
Blitz3D Forums/Blitz3D Beginners Area/The use of TFormVector
| ||
Hi, I just purchased Blitz3D and was looking around the docs at the commands and such. I have begun working on my own little secret project :) Well anyway the question of what importance is the x,y,z of the vector? Thanks |
| ||
x,y,z is what defines the vector ... I guess I'm not sure what your question is. TFormVector is used to translate a vector from one space to another. So from local space to world space, for example. |
| ||
i always use x ie tformvector 1,0,1,x,ent1,ent2 if thats what your asking which gives me the correct results in 3d. |
| ||
oh okay I think I will try that thanks sinu and EpicBoy |
| ||
Vectors are used to represent a lot of things. The direction a vertex points for when you're doing lighting. The direction a face points, for hidden surface removal. The speed and direction your objects in your game are moving. The TFormVector TFormPoint and TFormNormal commands are very powerful and allow you to transform/rotate/scale vectors and points from one space into another. In other words, when you drive you car, it always moves along IT'S Z axis, but it does not always move along the Z axis of the WORLD. The car and the world have different coordinate spaces. All vertex positions for the car are in car space. The End. |
| ||
Hmm... this is all rather confusing :) Basically I am trying to use a vector to find the distance between two points. My code looks like this TFormVector par1\oldx,par1\oldy,par\oldz,par1,par2 vx= TFormedX() vy= TFormedY() xz= TFormedZ() delta_length= Sqr(vx*vx)+(vy*vy)+(vz*vz) Where par1 and par2 are the two points I am finding the distance between and vx,vy and vz are the vectors positions. From what I have read here it dosen't look like I am doing it right :/ |
| ||
That's entirely the wrong tool for the job. TFormVector translates a vector from one space to another, it doesn't measure distance the between two entities. Check out EntityDistance. If you don't want to do the calc yourself, just create two pivots at the appropriate locations and do an EntityDistance on them. |
| ||
What would be the right way to go about it then??(without using EntityDistance) Thankyou for putting up with my my ignorance :-) |
| ||
D# = Sqr((X1#-X2#)*(X1#-X2#) + (Y1#-Y2#)*(Y1#-Y2#) + (Z1#-Z2#)*(Z1#-Z2#)) That's the fast way. Use if you're gonna call it a thousand times a frame. D# = Sqr((X1#-X2#)^2 + (Y1#-Y2#)^2 + (Z1#-Z2#)^2) This is the math way. X^2 is slower than X*X. Takes less typing and looks cleaner so use this if you're not calling it often. D2# = (X1#-X2#)*(X1#-X2#) + (Y1#-Y2#)*(Y1#-Y2#) + (Z1#-Z2#)*(Z1#-Z2#) Use this when you need to simply COMPARE two distances to dtermine if one object is farther away than another, and you intend to make that comparison a thousand times a frame for various objects. Ie, If (D2a# > D2b#) then object 1 is in front of object 2. Note that you can also use this trick of using squared distances to determine if an obejct is farther away than a certain distance. If D2# > (Distance*Distance) Then object is greater than distance away from whatever. |
| ||
If you want some real fps then try this:global dx#,dy#,dz#,dist# dx=x1-x2 dy=y1-y2 dz=z1-z2 dist=sqr(dx*dx+dy*dy+dz*dz) |
| ||
Have you actually benchmarked that to see if it's faster? Cause it's not always faster to remove redundant calculations. Especially when the redudancy is an add or a subtract which are very inexpensive operations. I'm pretty sure I alreay benchmarked that and determined it was not actually an optimization. |
| ||
Thanks for that distance equation swift :) I think someone should put a post in the tutorials with a list of equations, and their uses :) |
| ||
Thanks for the equations! I think someone should put a post in the tutorials with a list of equations, and their uses that would be a good idea especially for newbies like me :) |
| ||
There are a billion equations, and the use of many of them is not immediately apparent. :-) For example, I could tell you the plane equation, but that would be useless to you if you don't know enough math to find clever ways to make use of it because you don't understand what the equation represents. Look in the code archives for Ray Intersect Triangle, a function I wrote, and take a look at the source to that and you'll leanr how to determine if a ray is intersecting a triangle, but also how to use the dot product equation to determine how much a vector points in the same direction as another vector, and how to use the cross product to take two vectors and find a third which is at 90 degrees to them. (Ie, the normal of a triangle, if given two sides of the triangle for the vectors.) And that's just the tip of the iceberg. I have a whole text file full of various equations which are useful for making games, but right now they're probably too complicated for you to use if you just learned the distance equation. :-) |
| ||
I mean't just simple one's, such as 2 line interect, distance equation, acceration equations. Sorta basic one. I know a few basic one, but probably not enough to warrant a list :) |
| ||
sswift: I sure would like a copy of that text file full of equations. |
| ||
Okay. Here's the file. Of course I didn't write down every single equation I use in this file. :-) And there's some discussions I kept between me and some physics/math guys on a few of the more difficult subjects. ------------------------------- "I wish I could remember the math term for and how to caclulate that sort of comparison. Like if you have 5 vertcies, it's 5+4+3+2+1 which is 15 comparisons." - n(n+1)/2 is probably what you are looking for. --------------------------------------- Anyway, here's the logic for the friction force: suppose we've got a surface normal norm = (nx, ny, nz), and a gravity vector running in the y direction grav = (0, 1, 0). We take their vector cross-product to get a "sideways" vector sideways = (sx, sy, sz) = (-nz / n, 0, -nx / n) ...where n = sqrt( nx * nx + nz * nz) is a normalizing factor, to keep 'sideways' of unit length. n is also equal to the sine of the angle between 'norm' and 'grav'. Next thing to do is to vector-cross-product 'sideways' with 'norm', thereby getting a unit vector that's in the plane of the surface, going uphill: uphill = sideways x norm = (-ny * nx / n, (nz * nz + nx * nx) / n, -ny * nz / n) = (-ny * nx / n, n, -ny * nz / n) Now we gotta multiply 'uphill' by the sine of the inclination... which, as I mentioned a few paragraphs ago, happens to be n. So: friction_force = uphill * n = (-ny * nx, n^2, -ny * nz) = (-ny * nx, nx * nx + nz * nz, -ny * nz) ...which means that you can compute the force vector without having to do square roots or other unpleasant forms of math. Reducing velocity only in a direction perpendicular to the face collided with: ------------------------------------------------------------------------------ Assume V is the velocity vector and N is the normal. N is perpendicular to the surface and has length 1. The component of V in the direction of N is given by the dot product. If you wanted to reduce velocity by 10% in the N direction then you would subtract: V = V - 0.1 * (N dot V) * N ; pseudocode. Of course, in Blitz you have to handle the x,y,z components separately: Assume dot#, nx#, vx# etc. are all defined. dot = nx*vx + ny*vy + nz*vz vx = vx - 0.1*dot*nx vy = vy - 0.1*dot*ny vz = vz - 0.1*dot*nz (N dot V) * N is the projection of V onto N. OR.............. Dot# = NX * Item\SpdX + NY * Item\SpdY + NZ * Item\SpdZ ReflectX# = NX * Dot# ReflectY# = NY * Dot# ReflectZ# = NZ * Dot# ; 1.0 stops bouncing ; 2.0 produces a perfect bounce (no loss of energy) bounce# = 1.1 ; Retain only 10% of the energy Item\SpdX = Item\SpdX - ReflectX# * bounce# Item\SpdY = Item\SpdY - ReflectY# * bounce# Item\SpdZ = Item\SpdZ - ReflectZ# * bounce# <Polytope> max(|x|,|y|)=r, where max(a,b) = (|a+b|+|a-b|)/2 <sswift> if C is less than like 1... <sswift> That would tell you the points to plot.; <PdoX> so you mean, |x| + |y| - |xy| <= 1 <Polytope> combine them and you get ||x|+|y||+||x|-|y||=2r <sswift> is there an equation for abs too? :-) <PdoX> |x| = sqrt(x^2) <PdoX> though thats cheating <PdoX> sswift: When two objects collide with initial energies E_1 and E_2, they end up with final energies E_1' E_2' where E_1 + E_2 = E_1' + E_2' + Q, where Q is the energy lost <PdoX> (energy lost to vibration,etc. everything taken from kinetic energy) <PdoX> For elastic collisions, you have Q=0 <PdoX> For inelastic, Q=E_1+E_2 (all) <PdoX> actually, I need to be more careful here.. <PdoX> I'm in the Center of mass frame. Fixed point numbers: -------------------- Let's say that your range is [Ra .. Rb]. Ra can be a negative number or a positive number. So let's say you want to compress an angle from -180 to +180 in your fixed point representation, and let's say you want to use 2 bytes for your fixed point number. For that we use a value of 65536. (256*256) Then what you do to convert to fixed point is this: FixedNum = ((FloatNum-Float(Ra)) / Float(Rb-Ra)) * 65536.0 And then to convert back you do this: FloatNum# = ((Float(FixedNum) / 65536.0) * Float(Rb-Ra)) + Float(Ra) And THAT will work for any range. Before I made a mistake, and the range always had to start with 0. What THIS does is it first shifts the floating point number so it is in the range of 0..(Rb-Ra) So for example with -180 .. 180, RB-Ra is 360. So we get a range of 0..360. Then after doing that it's divided by the number of numbers in the range, in this case 360, which scales it down to a number 0..1, THEn that number is multiplied by our fixed point maximum number, which is 65536.0, and we end up with an integer from 0..65536. Then on the other end 65536 is converted back to 0..1, and then from there to 0..360, and then from there -180 is added to it which gives us our floating point number in the range of -180..180. Don't concern yourself with the MOD stuff, that's only if you want to wrap values, and you can do that to the value before you do this equation. Quaternions: ------------ A unit quaternion adheres to the following equation: W^2+X^2+Y^2+Z^2 = 1 finding uniform random points around a point on a sphere. --------------------------------------------------------- Find a point on the unit sphere: P = (a,b,c) The first step is to find a point N on the unit sphere which is 90 degrees (arc length) away. N = (a/sqrt(a^2+b^2) , -b/sqrt(a^2+b^2), 0) will work unless a=b=0. now let T = PxN. so P,N,T are at right angles to each other now let's see. we want to parameterize the circle of radius r centered at P R = P*cos(r) + N*sin(r)*cos(t) + T*sin(r)*sin(t) should work pick a random angle t between 0 and 360 and you have a random point in the circle So in sphere space using P(0,0,1) N(0,1,0) T(1,0,0): r = radius from point at 0,0,1 t = random number between 0 and 360 Rx = sin(r)*sin(t) Ry = sin(r)*cos(t) Rz = cos(r) Radius should be set randonly too. I think. I think I can clip radius to create a hole. Finding UNFORM random points on a sphere: (Ie: no pole clustering) ---------------------------------- choose a random angle t and a random number z between -1 and 1, then let r=sqrt(1-z^2), x=r*cos(t), y=r*sin(t). then (x,y,z) is a random point on the sphere (of radius 1, centered at the origin) OR: To generate a random point on the sphere, it is necessary only to generate two random numbers, z between -R and R, phi between 0 and 2 pi, each with a uniform distribution To find the latitude (theta) of this point, note that z=Rsin(theta), so: theta=sin-1(z/R) its longitude is phi. In rectilinear coordinates: x=R*cos(theta)*cos(phi) y=R*cos(theta)*sin(phi) z=R*sin(theta)=z Note that in both methods points will appear to be clustered if you attempt to step through it. The lattitude lines become more sparse as the longitude lines become more dense, so random points will be evenly distributed, but if you plot even lonigtude lines it will look wrong. <Polytope> there is an amazing fact, which I don't know how to explain without calculus. <Polytope> if you enclose a sphere in a cylinder (with no top or bottom) then the sphere and the cylinder have the same surface area. <Polytope> moreover,if you project from the cylinder to the sphere, towards the axis of the cylinder, then this projection preserves area. <Polytope> so, to choose random points on a sphere, you can just choose random points on a vertical cylinder, then project the points horizontally to the sphere. <monochrom> The height of the cylinder is the diameter of the sphere, right? <Polytope> monochrom: yes <Polytope> archimedes discovered this somehow, waay before calculus. this is astonishing to me --------------------------- "The extra 1m/s is therefore stored like a battery in form of kinetic energy in the object. If it would go upwards while it has the energy stored, it would use up that energy until the kinetic "battery" is used up." Hm... that gives me an idea... The correct way to model a ball would be to deform it when it hits the ground, and then undeform it over a period of time pushing it against the ground... This way the ball would actually be in contact with the ground much more often cause as it deforms it deforms downward maintaining contact with the ground. In my current system the ball doesn't deform. When it hits the gorund it instantly changes direction and loses contact with the ground. This means that ground friction is only applied for a split second. Of course, it seems odd to consider applying ground friction for an object moving in a direction away from the ground. You usually think of ground friction like ab object being slid over sandpaper. It doesn't make sense for it to affect the ball when it simply bounces straight up and down on the sandpaper, even if it's only doing it for a split second. So I wonder if perhaps the physics which I am using is far too simplified. But these are the physics they teach in high school and all over the web! Why are they teaching stuff that's wrong? I think maybe my idea about applying certain forces to certain "axis" would work. For example, the ground friction would be applied only to forces in the XZ axis relative to the normal of the surface collided with. IE, a sliding force along the surface would be damped, but vertical forces, (vertical relative to the normal of the surface that is) would not. If I went that route then I could apply a seprate model to forces which lie on the Y axis relative to the surface normal. So the "downward" force (downward realtive to the surface normal) when the ball hits the surface, would be cut by 50% on the rebound but the velocity on the XZ plane would remain untouched by the damping force. Then, if I combine that with the idea about deforming the ball, so that the ball stays in constant contact with the plane if it is rolling along it, and stays in contact much longer when it collides at a shallow angle to it an ounces back up... If I do that, then ground friction should be modeled more accurately and more consistently on systems which calculate the physics at diffrent speeds! :-) --------- quaterion is four numbers. One of them is w. The other three are x,y,z which give a vector ( axis ) around which to rotate. w is the cosine of half the angle of rotation. Dtermining if two line segments intersect: ------------------------------------------ Let A,B,C,D be 2-space position vectors. Then the directed line segments AB & CD are given by: AB=A+r(B-A), r in [0,1] CD=C+s(D-C), s in [0,1] If AB & CD intersect, then A+r(B-A)=C+s(D-C), or Ax+r(Bx-Ax)=Cx+s(Dx-Cx) Ay+r(By-Ay)=Cy+s(Dy-Cy) for some r,s in [0,1] Solving the above for r and s yields (Ay-Cy)(Dx-Cx)-(Ax-Cx)(Dy-Cy) r = ----------------------------- (eqn 1) (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx) (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay) s = ----------------------------- (eqn 2) (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx) Let P be the position vector of the intersection point, then P=A+r(B-A) or Px=Ax+r(Bx-Ax) Py=Ay+r(By-Ay) By examining the values of r & s, you can also determine some other limiting conditions: If 0<=r<=1 & 0<=s<=1, intersection exists r<0 or r>1 or s<0 or s>1 line segments do not intersect * If the denominator in eqn 1 is zero, AB & CD are parallel * If the numerator in eqn 1 is also zero, AB & CD are coincident If the intersection point of the 2 lines are needed (lines in this context mean infinite lines) regardless whether the two line segments intersect, then * If r>1, P is located on extension of AB * If r<0, P is located on extension of BA * If s>1, P is located on extension of CD * If s<0, P is located on extension of DC Also note that the denominators of eqn 1 & 2 are identical. Plane equation and Sphere/Frustum Intersection Tests ---------------------------- Ax + By + Cz = D A = y1 (z2 - z3) + y2 (z3 - z1) + y3 (z1 - z2) B = z1 (x2 - x3) + z2 (x3 - x1) + z3 (x1 - x2) C = x1 (y2 - y3) + x2 (y3 - y1) + x3 (y1 - y2) - D = x1 (y2 z3 - y3 z2) + x2 (y3 z1 - y1 z3) + x3 (y1 z2 - y2 z1) We'll need to figure out the plane equation for each one of those six planes: A*x + B*y + C*z + D = 0 ...that plane equation calculation can be done one-time whenever the view frustum is set up. Note that for an arbitary point (px,py,pz), the distance to the plane is: d = A*px + B*py + C*pz + D ...so for each vertex of your bounding volume, you can measure the distance to each of those planes. For a sphere: Just toss the center point of the sphere into the equation above - and if the (signed) distance places the center point more than 'radius' units outside any of the planes then you can cull the object. * In the plane equation mentioned above, (A,B,C) is the surface normal of the plane and D is the distance from the origin to the plane - measured such that D is positive for planes that face the origin and negative from those that don't. ------------------ Diffuse and phong lighting: ^N | Lÿÿÿ | R V \ÿÿ | / __/ \ÿ | / __/ \ | / __/ \ | /__/ \|// -------------.-------------- P ^ point under consideration It's important you know what these values actually are: N = surface normal L = unit vector between point and light V = unit vector between point and view R = light reflection unit vector (mirror of L about N) First, the diffuse relfection is given by the Lamertian Relfection equation: diffuse = Kd * (N dot L) Where Kd is the diffuse relfection constant. (N dot L) is the same as the cosine of the angle between N and L, so as the angle decrease, the resulting diffuse value is higher. Phong gave spectral reflectivity as: diffuse + Ks * (R dot V)^n other source: lambert's "the light is dependant on the angle it hits the surface" law. Use the dotproduct to get that value. Angle = Dotproduct( Normal, vLightVector ); If Angle is negative then the light doesn't reach the point, otherwise use the Angle multiplied with the light's color as the diffuse component. Oh, by the way, colors are in the range [0.0, 1.0]. How to calculate the new vector of a ball which has struck a wall. (Also the normal force?) ------------------------------------------------------------------ v = v - 2*n*(v . n) (v . n = dot product of v and n... see below.) Dot product of two vectors: --------------------------- AdotB = ax*bx + ay*by + az*bz Air Friction: ------------- Here's how to compute air friction: air_friction_force = air_friction_constant * vehicle_velocity^2 A good air friction constant might be 0.2 Then: new_velocity = old_velocity - air_friction_force * time --------------------------------------------------------------------------------------------------------------- The "normal force" - How to make an object "richochet" off a surface, or move downhill when pulled by gravity. --------------------------------------------------------------------------------------------------------------- When an object impacts a surface, whether it is fired from a cannon, or is simply being pulled downwards by gravity, a "normal force" is generated which is equal in strength to the forces which were acting on the object when it hit. This "normal force" (NF for short), is ALWAYS perpendicular the the surface. Making pool balls bounce off bumpers and making a ball roll down a hill is done in the same way, and is very simple to do. All you have to do is find the velocity vector of the ball when it hit. In other words, add up the forces acting on it, like gravity, and the force applied to it when it was fired from the cannon. Then when the ball hits the surface, calclulate a vector which is perpendicular to the surface, and which has the same magnitude as the forces which were acting on the ball at that moment, and add theforce vector of the ball to the normal force... The result will be a vactor which points in the expected direction. For example, if you have a flat section of land, the normal force is straight up. And the force acting on the ball, gravity, points straight down. When you add them, they cancel eachother out exactly and the ball doesn't move at all, just as you'd expect. If on the other hand the ball is rolling across the surface in addition to being pulled down by gravity, then the ball will continue to roll across the surface, but will still not move downwards at all. Now if you have a hill, then the normal force points away from the hill... not straight up like on the flat plane example. So when you add the NF to the gravity acting on the ball, the result is a vector which points down the hill... so the ball rolls down the hill as expected! ----------------------------------------------------- Finding the closest point on a line to another point. ----------------------------------------------------- (x1, y1, z1), (x2, y2, z2) = ends of line segment (x3, y3, y3) = point u = (x3 - x1)(x2 - x1) + (y3 - y1)(y2 - y1) + (z3 - z1)(z2 - z1) ----------------------------------------------------------- (x2 - x1)(x2 - x1) + (y2 - y1)(y2 - y1) + (z2 - z1)(z2 - z1) u = the location between the two end points of the line which is closest to the point. If u is not between 0 and 1 then the closest point is not between P1 and P2 ---------------------------- LINE-SPHERE-INTERSECTION ---------------------------- To find out if a line intersects a sphere, find the closest point on the line to the center of the sphere. Then calculate the location of that point using U. And finally, find out the if the distance from that point to the center of the sphere is less than the radius of the sphere. ------------------ DEGREES TO RADIANS ------------------ R = D * (Pi / 180) ------------------ RADIANS TO DEGREES ------------------ D = R * 180/pi -------------------------------------------------------------- The angle to change a wheel for movement over a given distance. -------------------------------------------------------------- A = angle in radians R = Radius of wheel D= Distance moved D = R * A A = D/R ----------- SOUND ----------- Volume = the volume of the sound. MinDist = The distance at which the sound is at 100% volume. The sound will not get any louder closer than this. This has a big effect on how quickly the sound falls off. Since the sound card cannot make sounds that are extemely loud, it's probably best to set this value to around 1 meter, in your game units. Ie, 64, if 64 units equals a meter in your game. SoundDistance = The distance to the sound. maxvolume = the maximum volume of your sound. Volume = (MinDist^2 * MaxVolume) / (SoundDistance + MinDist)^2 ----------- DISTANCE ----------- dist = sqrt( (x1 - x2)^2 + (y1 - y2)^2 + (z1 - z2)^2 ) ------------- CIRCUMFERENCE ------------- C = 2PiR Circumfurence = 2 * Pi * Radius -------- MOMENTUM -------- P=MV Momentum = Mass x Velocity ------------------------------ POINT BETWEEN TWO OTHER POINTS ------------------------------ CX = AX + D * (BX-AX) CY = AY + D * (BY-AY) D = Distance 0 .. 1 (AX,AY)(BX,BY) = Endpoints of line segment AB. ------------------------------------------ POLAR COORDINATES TO CARTESIAN COORDINATES ------------------------------------------ X = Radius * Cos(Theta) Y = Radius * Sin(Theta) Converts polar coordinates into cartesian coordinates. Drawing a pixel at X,Y for Theta 0..360 at a fixed radius would draw a circle. ------------------------------------------ Angle of a point from 0,0 ------------------------------------------ Angle = ARCSIN(Y/R) or Angle = ARCCOS(X/R) ------------ NORMAL FORCE ------------ Fn = Fg * Cos(Theta) If on a slope, Fn = Normal Force Fg = Force of gravity Theta = Angle of the slope The normal force is the force perpendicular to the angle of the slope, which needs to be added to the force of gravity to determine how much accleration from gravity will actually affect the object. ----------------------------------- CONVERTING A FORCE INTO XYZ VECTORS ----------------------------------- Mxz = M * Cos(Ty) Fy = M * Sin(Ty) Fx = Mxz * Cos(Txz) Fz = Mxz * Sin(Txz) This equation converts a vector described in the polar coordinate system to one in the cartesian coordinate system. The force is described with a magnitude (M) and two angles, an inclination (Ty) and a direction (Txz) on the XZ plane. Fx, Fy, and Fz are the resulting forces on each axis. ------------------------------ CALCULATING THE CENTER OF MASS ------------------------------ Total_Mass = (mass1 + mass2 + ...) x3 = (mass1*x1 + mass2*x2 + ...) / Total_Mass y3 = (mass1*y1 + mass2*y2 + ...) / Total_Mass z3 = (mass1*z1 + mass2*z2 + ...) / Total_Mass Calculates a scaled average of the locations so that the center is closest to the more massive objects. -------------------------------------------- CALCULATING THE CROSS-PRODUCT OF TWO VECTORS -------------------------------------------- v and w are two vectors in 3-dimensional space v x w (read "v cross w") is a vector whose magnitude is the product of the magnitudes of v and w, that is perpendicular to both v and w, and whose direction is given by the right-hand rule. To compute a cross-product, usually what you end up doing is computing a determinant. Write a 3x3 matrix with the first row being the components of v, the second row being the components of w, and the third row being the unit vectors, i j k. The determinant of that is the cross-product of v and w abc = xyz force 1 def = xyz force 2 (a,b,c) * (d,e,f) = (bf-ce, cd-af, ae-bd) ------ TORQUE ------ The torque generated by a force on a system is given by r x F. r = The position vector of the point where the force is applied relatively to the center of mass. F = A force vector. r = (a,b,c) F = (d,e,f) T_F = (bf-ce, cd-af, ae-bd) T_F is the torque generated by F. So you compute the torques generated by all forces you sum them (vector sum) and then you divide the resulting vector by the "moment of inertia" "moment of intertia": it's a measure of the system's "resistance" to rotation, if you want it's a function of the point masses and their distance from the center of mass are your "rods" mass-less? then you just need to sum up m_i * r_i^2, i *think* where m_i is a point mass, and r_i is its distance from the center of mass divide the sum of torques by that quantity, and that's the angular acceleration vector so if you have 2 objects, one with mass 1kg at 2 meters, and another with mass 2kg at 3 meters, the unnamed quantity is 1*2^2 + 2*3^2 = 22 to get the linear acceleration of a point from that, you compute (angular acceleration) x r where r is the position vector of a point relative to the center of mass x denotes a cross-product, again the angular acceleration is a global measure of the rotational acceleration of the system but, something close to the center of mass accelerates less (linearly) than something far from it you take the A x r cross-product to take that into account A x r will give you an acceleration vector, which you can add to the acceleration vector resulting from the sum of forces (which we computed a while ago) the sum of those two is the acceleration of an individual point in the system acceleration of system's center of mass = sum of forces / mass of system -------- SPRINGS -------- http://www.pcug.org.au/~apurdam/doublespring/doublespring.html two masses, connected by one spring: M1, M2 = masses k = coefficient of stiffness of the spring x1, x2 = the displacements of the masses from their positions of equilibrium x1'', x2'' = the acceleration for M1 and M2 r = viscous damping x1', x2' = velocity of masses (from previous frame?) x1''= k / (M1*(x2-x1)) - r*x1' x2''= k / (M2*(x1-x2)) - r*x2' misc notes: Logarithmic Impulse formula. Impulse = Log(RestSpan) - Log(CurrentSpan) Note: this is a different from the usual linear spring formula which is taught in physics classes. With the logarithmic formula, it should be impossible to completely compress the spring. It also means that springs that have long rest lengths vibrate much slower than short ones. --------- Jet thrust against atmosphere --------- throtte = 0..1 thrust = throttle * max( max_thrust * (max_height - height) / max_height, 0) ------------------------------------------------------------------------ Only allowing velocity along a specific axis or in a specific diredction ------------------------------------------------------------------------ If you have a vehicle like a hovercraft, then it's okay to allow the hovercraft to have inertia and slide around in any direction. But if you have a wheeled vehicle, or a tank, then you won't want the vehicle to slide sideways if it's on an incline... you only want it to be able to roll forward or backward. This is pretty easy to fix. Take your vehicle's momentum which you've just calculated by adding it's moemntum from the previous frame and adding the forces acting on the vehicle, and convert it into an angle and a magnitude. A = The angle, B = the magnitude. C = The angle your tank is facing. Note that this can be totally diffrent from the angle the tank is trying to move in. Now do the following calculation: D = A-C D is the angle of your momentum vector if it were translated into a space where A = 0... where your tank is facing along the X axis. Now, create a new vector... where D is it's angle, and B is it's magnitude. Next, convert the vector into X and Y components. Then discard the Y component of the velocty, because that doesn't lie on the axis the tank can roll along. The value you have remaining, X, is the amount of velcoity which is along the axis the tank can move along. Finally, use X as your magnitude, and C (your tanks face driection) as your angle. That is your tank's new momentum vector. Convert it into X and Y components if need be. Note that you only want to do this sort of thing when your tank is on the ground. And you might want to do some aditional calculations... for example, your tank might be able to move along the Y axis, but there might be a lot of friction if it does so. So if you tank is moving sideways through the air fast, when it lands, you might want it to slide a bit before coming to a stop. If you give that axis a lot of friction and add the remaining velcoity to the forwar dmomentum then you can allow for that. Bresenham's lines drawing algorithm: public void lineBresenham(int x0, int y0, int x1, int y1, Color color) { int pix = color.getRGB(); int dy = y1 - y0; int dx = x1 - x0; int stepx, stepy; if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; } if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; } dy <<= 1; // dy is now 2*dy dx <<= 1; // dx is now 2*dx raster.setPixel(pix, x0, y0); if (dx > dy) { int fraction = dy - (dx >> 1); // same as 2*dy - dx while (x0 != x1) { if (fraction >= 0) { y0 += stepy; fraction -= dx; // same as fraction -= 2*dx } x0 += stepx; fraction += dy; // same as fraction -= 2*dy raster.setPixel(pix, x0, y0); } } else { int fraction = dx - (dy >> 1); while (y0 != y1) { if (fraction >= 0) { x0 += stepx; fraction -= dy; } y0 += stepy; fraction += dx; raster.setPixel(pix, x0, y0); } } } Lighting: <Jaia> 1/x^2 is all nice and good <Jaia> but there are 2 problems <Jaia> first it blows up at the source, x=0 <Jaia> so we must start at some small but non-0 x <Jaia> 2nd it never quite hits 0 though it gets close <Jaia> so we must modify it a bit <Jaia> the distance we need to get to is R <sswift> So lets say I wanted the version that blows up... how would I do that, just for the sake of argument? <Jaia> well you can use it directly B(x) = 1/x^2 <Jaia> but the 2 problems remain <Jaia> near x=0 it blows up <sswift> Cause I can make 0 distance a special case, and clamp the value to 255. <Jaia> that's no good <sswift> But that doesn't take R into account <Jaia> since for x small but non0 it gets arbitrarily high <Jaia> so simple claming is not a good idea <Jaia> well we need to take R into account <Jaia> this relates to the 2nd problem <Jaia> basically R sets our scale <Jaia> so really x/R is what is important here <Jaia> x/R is 'normalised', it goes from 0 to 1 <sswift> I know someone gave me a simpler equation a long time ago which created an expoential curve between two points... <sswift> I used it to make craters. <Jaia> do you want exponential or 1/x^2? <Jaia> they are quite different <sswift> They are? <sswift> :-) <sswift> I tohught light fell off expoentially. <Jaia> yes <Jaia> e^(-x) is finite at x=0 <Jaia> and decays must more rapidly <Jaia> 1/x^2 is a more accurate model <sswift> And you know this how? :-) <Jaia> since as you propagate the area of the spherical fronts of the light wave <Jaia> goes as x^2 <sswift> You know about lighting? :-) <Jaia> so the light intensity goes as 1/x^2 <Jaia> it's an area so it goes as ~ x^2 <Jaia> so we want the inverse of that <Jaia> (with some constant of course but we care about overall dependence) <Jaia> here is something you can do <Jaia> x/R goes from 0 to 1 <Jaia> so let's split it into 100 <Jaia> x/100R <Jaia> this is our tick mark <Jaia> i mean, R/100 <Jaia> so we have something like <Jaia> (R/100)^2 / (x + R/100)^2 <Jaia> notice this is equal to 1 at x=0 <Jaia> and then fall off as the inverse square as we want <Jaia> so all it remains is to multiply by 255 <Jaia> 255(R/100)^2 / (x + R/100)^2 <Jaia> so at x=0 the value is 255 as desired and it will fall off in the desired way <sswift> okay <Jaia> at x=R we have 255/(101)^2 << 1 <Jaia> which is quite small <Jaia> basically the tick mark is R/100 <Jaia> we have 100 of these to get to R <Jaia> each time i double the tick marks, i quarter the intesity, etc. <sswift> So what's better or worse aobut this question than the other one you gave me? <sswift> equation <Jaia> well ... this one is slightly more accurate <Jaia> the other one was exactly 0 at x=R <Jaia> but at the expense of bending the 1/x^2 falling off rate a bit <Jaia> to push it down enough <sswift> If it's below 1 at R, then it'll be clamped cause I have integers. <Jaia> but here it's so small at x=R it's totally fine <sswift> So... <sswift> this 100 bit... <Jaia> 255(R/5)^2 / (x + R/5)^2 <Jaia> use that then <sswift> Does it matter at all what that number is> <Jaia> this is enough <Jaia> no no ... <Jaia> 255(R/20)^2 / (x + R/20)^2 <Jaia> yes <Jaia> 255/(number+1)^2 is the value at x=R <Jaia> so i use 20 <Jaia> 255/(21^2) < 255/400 < 0.5 <Jaia> so we're ok <Jaia> 255/(21^2) < 255/400 < 0.8 <Jaia> anyway <sswift> So.... <sswift> What if I use a really large number there? <sswift> That would mnake it more accurate? <sswift> closer to 0? <Jaia> no, not really ... <Jaia> this is a little bit cheating <Jaia> the requirement that it's "negligible" at x=R is somewhat artificial <Jaia> and not precise <Jaia> it's very vague in fact <Jaia> the most sensible thing to do i think, without any other info <sswift> Will it change the visible appearance of the lighting in any way? <Jaia> is to make it just barely small enough at x=R <Jaia> oh yes <sswift> How so? <Jaia> if you make that number huge <Jaia> it will drop off immediately <Jaia> near the source <sswift> oh <Jaia> and will be almost 0 throughout the whole range from 0 to R <Jaia> that's like pushing R very far off <Jaia> so that the tail of 1/x^2 is very small <Jaia> i would make the tail just barely small enough at x=R <Jaia> just below 1 <Jaia> so it fits your requirement <Jaia> but still shows decay over the range <sswift> That sounds like in my crater simulation... I could increase the exponent to ^3 ^4... and that would push the crater wall off into the distance. <Jaia> without dying too quickly <Jaia> and being uninteresting <Jaia> right <Jaia> 20 might be ok <Jaia> 255(R/20)^2 / (x + R/20)^2 <Jaia> this is saying "R is quite far, but not extremely far so that most of the range the intensity is tiny" <sswift> Okay <sswift> I think I understand. If I have a problem I can tweak it to get it to look right by increasing ro decreasing that value. <Jaia> to give you an idea <Jaia> look at the value at x = R/2 <Jaia> halfway <Jaia> it will be 255/(11)^2 = 255/121 ~ 2 <Jaia> from 255 to 2 halfway <Jaia> this is a good check to see if it fits what you want <Jaia> whatever c you pick <Jaia> 255(R/N)^2 / (x + R/N)^2 <Jaia> N rather <Jaia> for x=0 it's always 255 <Jaia> for x=R/2 it's 255/(N/2 + 1)^2 <Jaia> and for x=R it's 255/(N+1)^1 <Jaia> and for x=R it's 255/(N+1)^2 <Jaia> so this should give you a good idea <sswift> The lightness will drop to 2 halfway to R with a value of R/2? <Jaia> from 255 to 2 <Jaia> as you go from 0 to R/2 <Jaia> (on your way to R) <Jaia> if that seems too low, drop N a bit <Jaia> to 16 say <sswift> Tht's increasing N. :-) <sswift> Okay <Jaia> then at x=R it's 255/17^2 = 255/289 < 1 The Attenuation Function 1 / ( c0 + c1 * d + c2 * d * d ) *By Setting the constants c0, c1 & c2, you can adjust the falloff ramp of the light *Setting c1 = 0, c2 > 0 will give you a radial distance squared falloff *Setting c1 > 0, c2 = 0 gives a linear falloff *Attenuation denominators less than one will give very large factors, thus making the light too bright close up *To avoid this, make sure c0 is set To some positive number, 1 Or greater <Jaia> 1/(x^2 + c) <sswift> what is C <Jaia> well, let's see <Jaia> at x=0 we get 1/c <Jaia> so we'll add another constant d <Jaia> d/(x^2 + c) <Jaia> d/c = 255 <Jaia> so x is given in the same units as R is? <sswift> yes <Jaia> ok <Jaia> d/(x^2/R^2 + c) <Jaia> at x=R we'll set it to 1 <Jaia> d/(1+c) = 1 <Jaia> d = 1+c <Jaia> 255c = 1+c <Jaia> c = 1/254 <Jaia> d = 255/254 <Jaia> change the value of d/(1+c) if you want <Jaia> this is the value at x=R <Jaia> d/c=255 is fixed <Jaia> d/(1+c) is the final value, play with it if d/(1+c) = 1 seems no good <Jaia> so we get as an idea <Jaia> (255/254) / (x^2/R^2 + 1/254) <sswift> Is that it? <sswift> :-) <Jaia> yup <Jaia> play with d/(1+c) as i said <Jaia> (you always have d/c = 255) <Jaia> d/(x^2 + c) is our general rule <Jaia> d/(1+c) gives the value of intensity at R <Jaia> i set it to 1 here <Jaia> (255/254) / (x^2/R^2 + 1/254) <Jaia> and got that <Jaia> and got that <sswift> Why did you not set it to 0? <Jaia> you can't <Jaia> this function is never 0 <Jaia> d/(1+c) = 0 <Jaia> d = 0 <Jaia> oops <Jaia> and besides <Jaia> make it too small <Jaia> will push out R too far <Jaia> effectively speaking <Jaia> as we discussed before <sswift> hm... <Jaia> your inensity will die out immediately <Jaia> and be tiny for most of the range <sswift> Could you perhaps make the range start at 256, go to 1, and then subtract 1 from the end result? <Jaia> if you want <Jaia> sure <sswift> Is there anyhtign bad about that? <Jaia> (256/255) / (x^2/R^2 + 1/255) - 1 <Jaia> not at all <Jaia> in fact it's a good idea <sswift> (256/255) / (x^2/r^2 + 1/255) - 1 <sswift> You typed it first <sswift> :-) <Jaia> that looks ok <sswift> at least I know I was right <Jaia> in general <Jaia> d / (x^2/R^2 + c) - d/(1+c) <Jaia> d/(1+c) is what your value at R would have been <Jaia> so it will be useful to see how far you're pushing R <Jaia> as before <Jaia> 256c / (x^2/R^2 + 1/255) - 256c/(1+c) <Jaia> c is our free parameter <Jaia> the last term, 256c/(1+c) sets the scale <Jaia> is it's much less than 1, it probably dies too quickly <Jaia> i'd keep it around 1 or 2 or so <Jaia> but maybe higher even <Jaia> play with it <Jaia> in all cases the value at R is 0 <Jaia> oh no ... <Jaia> ack <Jaia> d / (x^2/R^2 + c) - d/(1+c) <sswift> ack what <sswift> :-) <Jaia> d/c - d/(1+c) = 255 <Jaia> d = 255/(1/c + 1/(1+c)) <Jaia> so this is d in terms of c <Jaia> 255/(1/c + 1/(1+c)) / (x^2/R^2 + c) - 255/(1/c + 1/(1+c)) / (1+c) <Jaia> that last term <Jaia> - 255/blah blah <Jaia> that's what you don't want too small <Jaia> set it to 1-5 or so <Jaia> and see how it works <Jaia> the lower it is, the faster it decays <sswift> what was wrong with this? (256/255) / (x^2/r^2 + 1/255) - 1 <Jaia> this is the case for 1 <Jaia> it may work well <Jaia> i just gave you a more general case <sswift> ah. <Jaia> where you can tweak the parameter at will <Jaia> just solve that last term <Jaia> 255(1/(c(1+c)) + 1) <Jaia> 255/(1/c + 1/(1+c)) / (x^2/R^2 + c) - 255/(1/(c(1+c) + 1) <Jaia> ... <Jaia> same thing <Jaia> just cleaned up a bit <Jaia> 255/(1/c + 1/(1+c)) / (x^2/R^2 + c) - 255/(1/(c(1+c)) + 1) <Jaia> the one you gave has - 1 <Jaia> as a case <Jaia> by changing c <Jaia> you can make the - number different <Jaia> for a certain c you get - 1 <Jaia> as you showed <Jaia> change c to get different values - something <sswift> Okay <Jaia> making that something bigger makes the decay slower <Jaia> etc. <Jaia> etc. <Jaia> unless i made a mistake <Jaia> let me see <Jaia> d/(x^2/R^2 + c) <Jaia> d/(x^2/R^2 + c) - d/(1+c) <Jaia> d/c - d/(1+c) = 255 <Jaia> d = 255/(1/c + 1/(1+c)) <Jaia> ya, looks ok lighting -------- ; DX7 Lighting equation: ; Attenuation = 1 / (C0 + C1*D + C2*D*D) ; ; For some reason this equation does not seem to produce the expected results! ; ; In Blitz: ; C0,C2 = 0. C1=Light radius. ; ; Mark has said that Blitz's lighting follows this equation: ; Brightness = 1.0 / (Distance / Light_Radius) ; ; Which does what the DX7 equation should do, but I don't know why they're so different. ; ; The shadow system on the other hand uses a modified linear falloff. ; ; This is so that the distance at which the shadow attenuates completely is not really ; far away from it's origin. If we used the other equations, a caster would almost ; never be outside a light's range, and that would be very bad for the framerate! ; Standard linear falloff equation: ; ; L = Lightness ; R = Light max radius ; D = Distance from light ; ; L = (R - D) / R ; Linear falloff, modified to be offset so that: ; ; If D < R1 then L > 1 ; If D = R1 then L = 1 ; If D >= R2 then L = 0 ; ; L = (R2 - (D-R1)) / R2 Light_Falloff# = (R2# - (Vdist# - R1#)) / R2# ; Clamp the falloff value if we are outside max_range, or inside min_range. If (Light_Falloff# < 0) Then Light_Falloff# = 0 If (Light_Falloff# > 1) Then Light_Falloff# = 1 ; Convert the falloff value to a color for this vertex. Light_Falloff# = 255.0 * (1.0 - Light_Falloff#) a = 1 / (c0 + c1*d + c2*d*d) converts to: v = light_r * light_min_radius / distance Which can be inverted to: d = light_r * light_min_radius / v To find out the distance at which v becomes some value. |
| ||
that's some nice stuff. saved it, thanks |
| ||
whoa! Thanks man :) Longest post ever, worth it tho :) |
| ||
Thanks alot sswift: I should get lots of help from this list. |