Physics for Stupid People like me

Blitz3D Forums/Blitz3D Beginners Area/Physics for Stupid People like me

Eric(Posted 2004) [#1]
Where is a good place to learn about Physics, For games, where they go over the formula in basic steps.
I have played around with Tokamak, and want to try to do some things on my own.

First I am trying to have a player slid down a ramp, and at the bottom fly off with believable physics (like a Ski jumper). If the player doesn't have enought forward velocity, he wouldn't even make it off the ramp.

Can someone point me to a great site, that explains these types of physical simulations.

Thanks,
Eric


eBusiness(Posted 2004) [#2]
Dunno about sites, but to do what you describe (with Blitz collisions), set collision type 2, set three variables for the objects movement vector, for every loop:
Subtract a gravity constant from the y-vector
Store the object position in three extra variables
Move the object acording to the movement vector
Call UpdateWorld
Set the movement vector to the objects new position, minus the old position that you stored

This does not take friction into account

If you want the object to be bouncy replace the last line with:
Set the movement vector to (the objects new position, minus the old position that you stored)+a*((the objects new position, minus the old position that you stored)-old movement vector)

Set a to a number between 0 and 1, 1 for full bounce.

Edit: Ehhh, skip what I said about bouncing, there is a flaw making the bounce sorta random, the rest should work though.


eBusiness(Posted 2004) [#3]
Oh, whatever, you better learn it yourself. Vector math is inevitable http://www.physics.uoguelph.ca/tutorials/vectors/vectors.html

Hmmm, something's missing from that site, dunno what it's called in english, I'll try a search.


eBusiness(Posted 2004) [#4]
Projecting, found this http://chortle.ccsu.edu/VectorLessons/vectorIndex.html should contain all about vectors. Now we just need the physics.


Eric(Posted 2004) [#5]
Hey thanks, I glanced at it and will really learn something from this, I hope!! hahah Thanks

Eric


AbbaRue(Posted 2004) [#6]
You could start with "A Brief History of Time by Stephen Hawking "
That covers the topic of the formation of the Universe, and should give you some background.
Or you could go to the following website, which explains things in more Computer related terms.
http://www-courses.cs.uiuc.edu/~cs318/lectures.html
And down the page on the following site you have other coarse pages:
101, 125, 225, 231, 232, 273, 290, 296, 299, 311, 321, 323,
http://www-courses.cs.uiuc.edu/
You will need Adobe Acrobat for this because it's in .pdf format.


Take your choice.


Zethrax(Posted 2004) [#7]
Do a google search for "Chris Heckler" and "Jeff Lander". Both very cluey blokes in regard to game physics.

Also check out the physics articles at http://www.gamedev.net/ , http://www.gamasutra.com/ and similar sites.

There's also several different physics engines in the 3d code archives on this site, which are worth checking out. There are some physics tutorials over at http://www.blitzcoder.com/ , too.

One thing I've found with physics is that the standard newbie method of integrating physics, using simple euler integration ( velocity = velocity + thrust : position = position + velocity ), doesn't cut it due to numerical instabilities that end up causing an accumulation of energy. There are various other methods of integrating physics, such as verlet, runga katta 4, etc, which you should also look into.


eBusiness(Posted 2004) [#8]
due to numerical instabilities
You talk about the bouncing ball right? Going higher and higher for no obvious reason. Normal flawy code is like this:
position=position+velocity
velocity=velocity+acceleration
If [ball hit floor] Then velocity=-velocity
The ball will gain more and more height, because when the ball hit the floor, first acceleration due to gravity is added, then velocity is inverted, resulting in the ball launching upwards with greater speed than it came down with, the fix however is simple:
position=position+velocity
velocity=velocity+½acceleration
If [ball hit floor] Then velocity=-velocity
velocity=velocity+½acceleration
This can be made a bit smoother:
position=position+velocity+½acceleration
velocity=velocity+acceleration
If [ball hit floor] Then velocity=-velocity



Physt(Posted 2004) [#9]
Coefficient of Restitution

If [ball hit floor] Then velocity=(-velocity * .92)

The ball loses energy when it hits the floors.


WolRon(Posted 2004) [#10]
Only superballs have a coefficient of 90%. All other balls have less.


CyberHeater(Posted 2004) [#11]
I think Sswift first posted this stuff. Some of it might be usefull.

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
--------

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.


sswift(Posted 2004) [#12]
All of my secrets, revealed! The horror!

Here's the latest version of that document. :-)




Eric(Posted 2004) [#13]
Wow you guys are pretty amazing, I wish I could just get my head around this stuff.

If I put my player on a slanted surface, and I align his vector to the surface normal, how can I determine the direction he should slide, and that he will pick up speed and then when the jump curves up he will follow it and launch off the end. What do I have to understand.

I have been reading a book about physics but when I try to put them on the computer it all fails.

What is the best way to understand this stuff.?

Best Regards,
Eric


sswift(Posted 2004) [#14]
"If I put my player on a slanted surface, and I align his vector to the surface normal, how can I determine the direction he should slide, and that he will pick up speed and then when the jump curves up he will follow it and launch off the end. What do I have to understand."


The first thing you need to do is revamp the way you move objects around.

Calculate the number of seconds a frame takes as a floating point number. To do this, determine the number of milliseconds between one frame and the next, and then divide that by 1000.

Next, specify a velocity for each of your objects in meters per second, or blitz units per second. If one Blitz unit is one meter, then you can easily use meters per second without concernign yourself with converting units. You want to use meters per second because so much of physics uses metric measurements of speed, metric measurements of mass, etc.

Next, for each object, store it's velocity on each axis. Ie, how far the object is moving in each direction in the world. Vx#, Vy#, Vz#. Initially, this will usually be 0.

This velocity vector stores both DIRECTION of movement, and SPEED. Alternatively, you could store the direction and speed of the object instead, but you will have to convert vack and forth between a vector and a speed and direction normal often when doing physics, so you might as well store the smaller of the two datasets.

Now, when you need to convert from a vector to a speed and direction normal you would do this:

Speed# = Sqr(Vx#^2 + Vy#^2 + Vz^2)
Direction_X# = Vx# / Speed#
Direction_Y# = Vy# / Speed#
Direction_Z# = Vz# / Speed#

What you end up with is a speed, and a vector with a length of 1... a normal, which defines the direction of travel.

To be continued...


sswift(Posted 2004) [#15]
Now that you have an object which has a velocity, let's accelerate it with gravity.

First, define your gravity normal. This is the direction in which gravity pulls the object. For most games, gravity will pull downward. But in space games, gravity will pull you towards the center of a planet.

But quickly... to calculate that planet gravity normal, subtract the position of the space ship from the position of the planet, and then normalize the vector. Normalizing the vector means convert it to a normal. And to do that, you do what I did above to what I will refer to as vector Vxyz... Vx, Vy, Vz. The normal is the direction.

But for your game, gravity probably points downward. And the normal for that gravity will always be 0, -1, 0.

Place those three values into Gx#, Gy#, Gz#, and you have your gravity normal.

On to part 3...


sswift(Posted 2004) [#16]
(Btw, I'm positng this in parts cause my PC tends to crash and I don't want to have to retype it all.)


Now that we have our gravity normal, we need to define the acceleration of gravity. Earth gravity accelerates an object at 9.8 meters per second squared. There's those meters I warned you about! This is where it things get very tricky if you don't have one unit equal to one meter. So for the sake of this tutorial, I will assume that is the scale of your world. One unit = one meter.

Now, what 9.8 meters per second squared means in layman's terms is that every second, your object will move 9.8 meters per second FASTER. So in the first second it will accelerate to 9.8 meters per second... and in the second second, it will acceltate to 19.6 meters per second.

Now here's how you make gravity affect an object.

; This can be computed once at the start of the program,
; unless you're doing space planet physics.
GravityAcceleration# = 9.8
Gvx# = Gx# * GravityAcceleration#
Gvy# = Gy# * GravityAcceleration#
Gvz# = Gz# * GravityAcceleration#


; Heres what you do each frame.
Vx# = Vx# + (Gvx# * FrameSeconds#)
Vy# = Vy# + (Gvy# * FrameSeconds#)
Vz# = Vz# + (Gvz# * FrameSeconds#)


Note how I am adding the gravity vector / force to the object's velocity. When a new force is applied to your object, you just add it to the object's vector. However, gravity is a bit different than other forces. With gravity, mass is not important.

Well... at the scale we are working at, it is not important. The earth does pull on the sun even as the sun pulls on the earth.

Note also that I have multiplied the gravity vector by the number of second the frame took.

The gravity vector says "I pull downward at 9.8 meters per second!" and the framesecond variable says "Oh yeah? Well you only have a tenth of a second this frame to act on the object, so you only get to accelerate it by an additional 0.98 meters per second!"

On to part 4...


sswift(Posted 2004) [#17]
Now let's set up some types for your players/objects...

Type Player
   Field Entity
   Field Vx#
   Field Vy#
   Field Vz#
End Type


Once you've done that, take all the Vxyz's I've written above and replace them with ThisPlayer\Vx# for example.

Then you can loop through all your players and do physics like so:

For ThePlayer.Player = Each Player
;Do physics here with ThisPlayer\Vx#, Vy#, Vz#.
Next


Then once you've done that, you can move on to the final step...

For ThePlayer.Player = Each Player
; Do some physics here.
; Check for collisions.
; If collision with level then bounce player off level.
; If collision with another player then bounce players off eachother.
TranslateEntity ThisPlayer\Entity, ThisPlayer\Vx#*FrameSeconds#, ThisPlayer\Vy#*FrameSeconds#, ThisPlayer\Vz#*FrameSeconds#
Next


Note how I have used translateentity, and not moveentity. The player's direction of movment is ultimately NEVER affected by the direction they are facing. Their face direction ONLY changes the direction of any thrust they apply to themsevles. That change in thrust direction is what changes their direction.

There are however certain exceptions to this rule if you want to do for example hover racing physics without getting into physics which are too complicated. But that is beyond the scope of this disucussion.

Now there's one last peice of the puzzle to make your object properly affected by gravity. And that is taking into account the surface normal and calculating rebound. But I don't think I'll write about that right now, I'm kinda tired of typing. :-)


sswift(Posted 2004) [#18]
Oh and btw... I just realised that what you are describing is a skateboarding simulation. I am not sure if the physics I am describing to you will be adequate for that. They are correct physics, but the physics of real life interactions is a LOT more complicated than the simplest case I am describing to you here. I am not sure that if you took my ball simulation and stuck it in a half pipe if it would behave as expected. Consider the difference between putting a rubber ball in a half pipe, and a bowling ball in a half pipe. The rubber ball as it rolls down the half pipe might at some point jump off the surface if it encounters any imperfections in the surface. And a polygonal model is FULL of imperfections. The surfaces are angular. So my ball simulation might jump off the surface. But not neccessarily for the same reason that that rubber ball might jump off the surface. It is a tough problem. I think it has something to do with elastic versus inelastic collisions.

Anyhow I'm not saying it won't work. I'm just saying I'm not sure if it will.

In other words, your problem may be too complex for you to solve. A skateboaridng simulation might not be the best way to first venture into physics. :-)


Eric(Posted 2004) [#19]
Swift,

I am preparing to print all that you wrote, You have explained quite a bit and I am getting ready to try to absorb it all.

My Game isn't really a game, I am just trying to learn how to make certain events happen.

Right now I have an Object that looks like a Childs sliding board except that at the bottom it curves up. I have a ball at the top that I want to roll down, and follow the curve.

I have been reading these boards for quiet some time, and I have really envyed your ability. I hope in the future you might help me to understand how to get these physics equations to work in a gaming environment.

Normalizing, Cross Product, Dot Product... When you have time... Can you please explain, how these will help me in programming.

Best Regards,
Eric


sswift(Posted 2004) [#20]
Normalizing makes a vector have a length of 1. This basically gives you a starting point... The normal tells you a direction something points, and because it has a length of 1, if you multiply it by a magnitude, say, 10, then it will have a length of 10. This length of 10 might represent a speed of 10 meters per second, or 10 blitz units per second, or it might be a distance to move a vertex away from the surface of an object.

A dot product is what you get when you multiply two normals with the dot product formula. Dot# = V1x#*V2x# + V1y#*V2y# + V1z#*V2z#

If the two normals point towards eachother, or away from eachohter, ie, in opposite directons, the result will be -1. If they point 90 degrees away from one another, ie, perpendicular to one another, the result will be 0. If one points away from the other, ie, they point in the same direction, the result will be 1.

The dot product is used for many things, but most often for calculating lighting. If you make a normal that points in the same direction a light points, and you have a normal for a vertex, or face, which tells which direction the vertex or face points, and you do a dot product, if the face faces towards the light, the result will be -1, and if it faces parralel to the light or away from the light, it will be between 0 and 1. This tells you exactly how bright the surface should be.


A cross product gives you a vector which is 90 degrees from two other vectors. In other words, if you make a vector that points down the Z axis, and a vector that points down the X axis, and do a cross product on them, the result will be a vector that points up the Y axis. This is how you calculate the normal of a polygon. You take two sides, calculate the cross product, and then normalize the vector so it has a lenght of 1, making it a normal.


Eric(Posted 2004) [#21]
Thanks...Still a blur, But in time it will all fit...

OK back to your original explanation. Now I have some of your formulae sorted... How do I add my own inputs to Direction... Now My Object is an Arrow. I want my Arrow to move in the direction it is facing. Using your equations.

I just am using my arrow keys, using the Turn Entity Command on the Z Axis.

So basically, I should just add an impulse to the Correct Axis, I'm assuming is the 'X' Axis.

And then add some sort of Friction to slow it Down.. Like
VX#=VX#*.95

Is my thinking in the right Direction?

Regards,
Eric


sswift(Posted 2004) [#22]
Unless your arrow is a missile, you do not want to apply thrust to it every frame, but rather apply an initial thrust to it, and then use air friction to slow it down.

To apply the initial velocity, do the following:

TFormNormal 0, 0, 1, Arrow, 0
Thrust_Nx# = TFormedX()
Thrust_Ny# = TFormedY()
Thrust_Nz# = TFormedZ()

You now have a direction normal that points in the same direction as your arrow is pointing.

Now, decide on how much speed you want to add to your arrow initially, in meters per second.

Thrust# = 10.0

Now, combine the two into a vector.

ArrowThrust_Vx# = Thrust_Nx# * Thrust#
ArrowThrust_Vy# = Thrust_Ny# * Thrust#
ArrowThrust_Vz# = Thrust_Nz# * Thrust#

You now have a vector which is 10 units long and points in the same direction as your arrow.

Now you just add this initial thrust vector to the arrow's thrust vector. It might, alter the arrow's direction of movement if it is in a different direction than the arrow is currently moving. You only do this ONCE when the arrow is released.

Arrow_Vx# = Arrow_Vx# + ArrowThrust_Vx#
Arrow_Vy# = Arrow_Vy# + ArrowThrust_Vy#
Arrow_Vz# = Arrow_Vz# + ArrowThrust_Vz#

Now, assuming your arrow was motionless when it began it is now moving at ten meters per second...

Oops, I just relaised I made a mistake in oen of my earlier posts.

This line:

TranslateEntity ThisPlayer\Entity, ThisPlayer\Vx#, ThisPlayer\Vy#, ThisPlayer\Vz#

Must actually be:

TranslateEntity ThisPlayer\Entity, ThisPlayer\Vx#*FrameSeconds#, ThisPlayer\Vy#*FrameSeconds#, ThisPlayer\Vz#*FrameSeconds#

I have corrected it.

This is because the velocity vecotr of the entity is how fast is is moving in meters per second, and each frame, we only want to move it the right distance for the time passed. Ie, is a tenth of a second has passed, we only move it at a tenth of it's current speed, so that when 10 frames have elaapsed, and an exntire second has passed, the arrow has moved 10 meters if it is moving 10 meters per second.


sswift(Posted 2004) [#23]
Now to do air friction...

To do physically correct air friction, you must convert the object's velocity vector into a speed and a direction.

I already told you how to do that above, but I will show you again here:

Speed# = Sqr(Vx#^2 + Vy#^2 + Vz^2)
Direction_X# = Vx# / Speed#
Direction_Y# = Vy# / Speed#
Direction_Z# = Vz# / Speed#

Once you have the speed and direction of the object, you can do this:

Air_Friction_Force# = AIR_FRICTION_CONSTANT# * Velocity#^2.0
Velocity# = Velocity# - (Air_Friction_Force# * Time_Delta_Sec#)

Time_delta_sec# is the name I use instead of FrameSeconds# for my frame timer. I left it like that so you wouldn't be confused if I paste other physics code from my games and forget to change the variables.

Velocity# here is also a different variable name I use. This time, it is the Speed# variable above. So this becomes:

Air_Friction_Force# = AIR_FRICTION_CONSTANT# * Speed#^2.0
Speed# = Speed# - (Air_Friction_Force# * FrameSeconds#)

Now you's asking yourself... What is air friction constant?

Air Friction Constant, is a value which is a combination of two factors. One is the viscosity of the air. Ie, how thick the air is. Air... water... they're the same thing basically in physics, except that water is thicker and thus causes more drag when you try to move through it quickly. The other is how areodynamic the object is.

In my games I do not differntiate between objects with regards to the amount of air friction they have. As far as I am concerned, they all have the same areodynamic properties, and so I don't have to combine their areodynamic value with the air's viscocity. I just chose a value which felt like an average air friction. For now, you don't really need to worry about whether an arrow travels through the air more easily than a person or a car or a rock.

Here are the constants I have defined for my physics:
Const GRAVITY# = 9.8
Const AIR_FRICTION_CONSTANT# = 0.2
Const GROUND_FRICTION_CONSTANT# = 0.5


sswift(Posted 2004) [#24]
Now that you have calculated the object's new speed after taking into account the amount of air frictoon at it's current speed, you need to convert it back to a velocity vector so you can store that and use it to move the object.

But first, you need to make sure your speed has not gone negative. Speed can never be negative in physics. If it is it just means your object stopped somewhere in the middle of the time tick you just calculated in your physics. Physics in games is an approximation. Like a sound is samples 44 thousand times a second, we sample our physics 60 times a second or more, but sometimes that is not enough to accurately represent the motion of the objects.

So...

If Speed# < 0 then Speed# = 0


And finally, we convert back to the vector:

Vx# = Direction_X# * Speed#
Vy# = Direction_Y# * Speed#
Vz# = Direction_Z# * Speed#


All done. Your arrow will now shoot out of your bow at 10 meters per second, and the air friction will cause it to gradually slow down (_very_ gradually, unless it is moving VERY fast, amd then it slows it down very quickly.) and it will fall towards the earth in a parabolic arc until it collides with it at which point it will probably slide along the ground because the air friction hasn't slowed it to a stop, and gravity is still pulling on it, and we have not modeled ground friction or loss of energy when the object strikes the ground.

But for simplicty's sake, when it hits the ground you could just set Vxyz# to 0,0,0 and turn off the other physics simulation.

Oh btw, an arrow will turn to rotate in the direction it is moving. You can simulate this by taking it's current position, subtracitng it from it's last position, and then using aligntovector() to align the arrow's Z axis to the XYZ vector you got when you subtracted those two positions from one another.


sswift(Posted 2004) [#25]
One last thing. Here is the formula to compute the effect of ground friction on an entity.

Air friction is very mild when an object is moving at a low speed... an object will coast forever with only air friction affecting it. But it kicks in when the object is moving really fast, so if you apply constant thrust, air friction will prevent the object from continuing to accelerate to thousands of miles per hour. That is what the velocity squared bit does.

Ground friction on the other hand does not depend on how fast the object is moving. Ground friction slows an object down at a constant rate. Ie, each second the object slides along the ground, it will move one meter per second slower.

Ground friction is was causes a fast moving object to slide along the ground rapidly, slow down quickly, and come to a jarring halt suddenly.

This is the ground friction equation:

Velocity# = Velocity# - (GROUND_FRICTION_CONSTANT# * Time_Delta_Sec#)

And note that here, just like with air friction, you MUST check to see if Velocity has gone negative and reset it to 0 if it has.

Actually... on second thought, checking with air frictioon might actually not be worthwile since it is probably impossible for the object to slow to 0 speed with air friction. But there's still a chance, and it doesn't hurt to be safe. Negative velocities make physics simulations blow up.


Eric(Posted 2004) [#26]
Shawn,

I have some of this Working, and I really appreciate you taking as much time as you did explaining this to me.

These Statments I understand, as I now have my Arrow Moving.

TFormNormal 0, 0, 1, Arrow, 0
Thrust_Nx# = TFormedX()
Thrust_Ny# = TFormedY()
Thrust_Nz# = TFormedZ()

Where does the Gravity Vector come into play. My Code Below is with your help, How do I add the gravity? I want to make sure when my character is heading up a hill, he starts to slide backwards if I apply no forward thrust





Why Doesn't My character Slide down the slop he is on?
I know you don't have the graphics, but I can climb up a slope but once I get up I can't go back down the slop. It's like gravity on a slop works in reverse.
Regards,
Eric


Zethrax(Posted 2004) [#27]
Something else to be aware of with physics is this nasty little bug I posted a bug report on several updates ago (link below). The bottom post in the bug report topic includes code to compensate for it.

http://www.blitzbasic.com/Community/posts.php?topic=27508


sswift(Posted 2004) [#28]
Why doesn't he slide down the slope? Because you've got the physics all wrong. :-)

Wrong:
Character\Vx# = ( Thrust_Nx# * Thrust#) + (Grav_Nx#*Gravity#)
Character\Vy# = ( Thrust_Ny# * Thrust#) + (Grav_Ny#*Gravity#)
Character\Vz# = ( Thrust_Nz# * Thrust#) + (Grav_Nz#*Gravity#)

I never told you how to apply thrust constantly, only how to apply instant thrust at the moment an arrow was released.

But I did tell you that when you add gravity you have to do something like Vx = Vx + Gx.

You're not even doing that here. You've got these equations all messed up.

Take smaller steps. You should have tried to get gravity working by itself first. Then gotten instant thrust working. Then you could have asked how to apply thrust over a period of time.


First off, this is all wrong:

If KeyDown(57)
If Not Animating(Character\body) Then Animate Character\Body,3,3,1
Thrust#=2
Else
Thrust#=Thrust#*.95
EndIf


Do this instead. This is how you apply constant thrust.
If your player keeps accelerating forever, that it CORRECT! That is not a mistake. The problem is that you are not simulating air friction to limit his top speed.

; If player is pushing forward, increase speed by 10 meters per second, per second.
If KeyDown(57)
Thrust# = 10.0
Else
Thrust# = 0
endif


Next, calcualte the direction of the thrust, which you have done correctly.

TFormNormal 0, 0, 1, Character\Body, 0
Thrust_NX# = TFormedX()
Thrust_Ny# = TFormedY()

Thrust_Nz# = TFormedZ()


Now, calculate the thrust vector.
Thrust_Vx# = Thrust_NX# * Thrust#
Thrust_Vy# = Thrust_NY# * Thrust#
Thrust_Vz# = Thrust_NZ# * Thrust#


And finally, add the amount of thrust that should be applied during the time this frame took.
Vx# = Vx# + Thrust_Vx#*PhysicsTime#
Vy# = Vy# + Thrust_Vy#*PhysicsTime#
Vz# = Vz# + Thrust_Vz#*PhysicsTime#


That means this:
PhysicsTime#=(MilliSecs()-Time)/1000.00

Belongs at the top of the physics, not down the bottom.


This is also wrong:
TFormNormal 0,-1,0,Character\body,0
Grav_NX# = TFormedX()
Grav_Ny# = TFormedY()
Grav_Nz# = TFormedZ()

This is right:
Grav_Nx# = 0
Grav_Ny# = -1
Grav_Nz# = 0


And this is wrong:
Character\Vx# = ( Thrust_Nx# * Thrust#) + (Grav_Nx#*Gravity#)
Character\Vy# = ( Thrust_Ny# * Thrust#) + (Grav_Ny#*Gravity#)
Character\Vz# = ( Thrust_Nz# * Thrust#) + (Grav_Nz#*Gravity#)


This is right:
Character\Vx# = Character\Vx# + (Grav_Nx#*Gravity#)
Character\Vy# = Character\Vy# + (Grav_Ny#*Gravity#)
Character\Vz# = Character\Vz# + (Grav_Nz#*Gravity#)


This is wrong:
LinePick EntityX#(Character\Body),EntityY#(Character\Body)+5,EntityZ#(Character\Body),0,-10,0,0.2
TranslateEntity Character\Body, Character\Vx#*PhysicsTime#,Character\Vy#*PhysicsTime# , Character\Vz#*PhysicsTime#
AlignToVector Character\Body,PickedNX#(),PickedNY#(),PickedNZ#(),2,.15


This is right:
TranslateEntity Character\Body, Character\Vx#*PhysicsTime#,Character\Vy#*PhysicsTime# , Character\Vz#*PhysicsTime#


You should not be using linepick to calculate the height of the ground, you should be using collisions to dtermine when the object hits the ground, that way you can find the angle of the ground beneath the player.

And you should not be angling the player to the angle of the ground.... unless you're doing a skateboard simulation...

Which may be why you were calculating gravity in that funny way... I suppose maybe you were trying to simulate centrifical force? To make the player stick to the half pipe? That's probably not the correct way to simulate that, but if it works for you... But add it AFTER you get the rest of the physics working!


Eric(Posted 2004) [#29]
Shawn,

Again, Thanks, I can honestly admit, that I tried to get the code to work with your previous explainations.. But I couldn't get it to work, so then I started playing around, and came up with the code that you just help me with. I am not a professional Programer, only a hobbyist, and the mathematical concepts elude me sometimes. So thanks for bearing with me. I will work with the examples you have laided out. Again, many thanks for taking the time.

Best Regards,
Eric


_PJ_(Posted 2004) [#30]
s=ut+1/2at^2

where u=initial velocity
s= horizontal displacement
a=acceleration
t=time

For a body after launch.


sswift(Posted 2004) [#31]
Whoopsie, made a mistake.


This is right:
Character\Vx# = Character\Vx# + (Grav_Nx#*Gravity#)
Character\Vy# = Character\Vy# + (Grav_Ny#*Gravity#)
Character\Vz# = Character\Vz# + (Grav_Nz#*Gravity#)


Actually, that is wrong.


This is right:
Character\Vx# = Character\Vx# + (Grav_Nx#*Gravity#)*PhysicsTime#
Character\Vy# = Character\Vy# + (Grav_Ny#*Gravity#)*PhysicsTime#
Character\Vz# = Character\Vz# + (Grav_Nz#*Gravity#)*PhysicsTime#


Eric(Posted 2004) [#32]
Shawn,

As I am looking at this Code,

Why do you Use PhysicsTime# in the above calculation and again in the Translate Entity command?

Regards,
Eric


sswift(Posted 2004) [#33]
Vx, Vy, and Vz are the speed and direction of your entity in meters per second on each axis of the world.

Let's say your entity is moving at 10 meters per second.

If the current frame only takes 1/10th of a second to render, then you only want to move the entity one meter that frame. That way, over the ovurse of a second the entity will have moved 10 meters.

If you did not scale the speed by the time a frame takes in seconds, then you would move the entity the same distance every frame, and the entity would move faster when you have a higher framerate, and slower when you have a lower framerate.


sswift(Posted 2004) [#34]
And the reason I use it here:
Character\Vx# = Character\Vx# + (Grav_Nx#*Gravity#)*PhysicsTime#

Is because...

Gravity increases your speed by 9.8 meters per second, every second.

So, if the current frame is only 1/10th of a second, the gravity only has time enough to accelerate the object by .98 meters per second.


Eric(Posted 2004) [#35]
Ok I got the code working, I am starting to understand how it all fits together. My character Continues in the direction I apply thrust. He is moving around like a space ship. Now I need to apply ground Friction. You told me to take this in pieces and that is what I am doing.



Here is where I am... Look just like you've instructed

I think :)

Eric


sswift(Posted 2004) [#36]
Yes, but adding ground friction will only cause the space ship to slow down when you let off the gas. It will not prevent it from accelerating forever.

If your ship won't move after you implement ground friction, then either you don't have enough thrust to overcome the ground friction, or the ground friction is too great.


Wayne(Posted 2004) [#37]
'You should not be using linepick to calculate the height of the ground, you should be using collisions to dtermine when the object hits the ground, that way you can find the angle of the ground beneath the player. '

I don't agree with swifts linepick statement. 8)
I agree the linepick originally shown is of no value.

I prefer to use linepick to determine if a collision occured anywhere along my vector of travel, and then calculate any refelection(s) and continue until my line segment is complete for the unit of time.

I do this because blitz collisions fail for smaller obejects moving at higher rates of speed over a mesh. I imagine the sphere passes completly thru mesh or whatever and no intersection exists.


sswift(Posted 2004) [#38]
I am trying to make this simple for him Wayne.

Of course one can use a line pick for collisions, but it makes things more complicated, and I have never encounted the problem you refer to with regular collisions except when dealing with Bltiz terrains. (The morphing appaears to screw up collisions.)

I had to choose one method to describe, so I chose the simplest one, which I use myself, and which works for most things perfeclty fine. :-)


(tu) ENAY(Posted 2004) [#39]
Where's all your Matrix maths? ;)


Eric(Posted 2004) [#40]
Ok Shawn,

How do I change my code, so my character moves like a person would move. hahah Not Like he's on Ice.. I am assuming I need ground friction. But where do I apply that force?

Regards,
Eric


sswift(Posted 2004) [#41]
"I am assuming I need ground friction. But where do I apply that force?"

At the start of the physics, before you add the thrust and gravity. Same for air friction.


sswift(Posted 2004) [#42]
Btw, for your game, you will probably want ground friction constant to be something you store in the player/enemy/item types. That way you can have a high ground friction constant for the player, but a lower one for an object like a ball.


Eric(Posted 2004) [#43]
I could actually change ground friction based on what I am standing on correct? Like looking at what texture is on a triangle and adjusting Ground Friction to that. Correct?

Ok..I add the same ground friction to Each of the Axis correct?

Regards,
Eric


sswift(Posted 2004) [#44]
"I could actually change ground friction based on what I am standing on correct?"

Yes, definitely, but I'm not going to work out how to determine what texture you're standing on for you. I haven't done it before, and it might be complicated. :-)


"Ok..I add the same ground friction to Each of the Axis correct?"

No.

Convert the vector to a speed and direction, as described above, do the following equation on the speed, clamp the speed to 0 if it goes below 0, and then convert back to a vector.


Speed# = Sqr(Vx#^2 + Vy#^2 + Vz^2)
Direction_X# = Vx# / Speed#
Direction_Y# = Vy# / Speed#
Direction_Z# = Vz# / Speed#

Speed# = Speed# - (GROUND_FRICTION_CONSTANT# * Time_Delta_Sec#)

If Speed# < 0 then Speed# = 0

Vx# = Direction_X# * Speed#
Vy# = Direction_Y# * Speed#
Vz# = Direction_Z# * Speed#


Eric(Posted 2004) [#45]
Ya know Shawn,

I think my problem is, that I can't visualize how all these calculations take place, and that's probably why this isn't catching on. Is this program that you have been helping me on. Have we used any Dot Products or Cross Product equivalents? I need to investigate Vectors and Scalars. If I could visualise what's happening. Where The vectors are pointing. Anyhow in your examples, part of my confusion is the Variables we have been using.. Just tell me 2 more things.. #1 Your variables above Vx,Vy,Vz...Are they refering to my Character\VX...Etc?

and #2... I want my character to Jump. Is that hard to incorporate?

Best Regards,
Eric


sswift(Posted 2004) [#46]
"Have we used any Dot Products or Cross Product equivalents?"

No.


"#1 Your variables above Vx,Vy,Vz...Are they refering to my Character\VX...Etc?"

Yes. I'm just using shorthand. Whenever I say Vx, I'm reffering to the Vx of whatever object it is you're doing the physics on at that moment.

"I want my character to Jump. Is that hard to incorporate?"

Not at all. A jump is a vertical acceleration. Rememebr the arrow example? Calculate your direction... which is 0,1,0 and then decide on the amount of thrust... say... 10 meters per second... And then multiply those together to get a vector as I showed with the arrow example... And then add the result to Vx Vy Vz... ONCE. The frame the player hits jump occurs, add it all, and then don't add any more.

Just make sure when the player hits jump that you check to see if they are colliding with the ground first. If they're not, then they can't jump... otherwise they'd be able to jump again while in the air. :-)

But you can worry about that later.


Eric(Posted 2004) [#47]
Shawn,

I got all your code working and it seems to be falling into place.

Please take another look at this code.

Notice I have 3 lines remarked out. Everything runs, without ground friction. Once I un remark these three lines.. All my variable go NaN. and nothing runs.. I tried to track it down in debug mode. But can't Can you help.


The lines are ;Vx# = Direction_X# * Speed#
;Vy# = Direction_Y# * Speed#
;Vz# = Direction_Z# * Speed#

Regards,
Eric


Friction#=0.5
gravity#=9.8
 
AngularV#=360
Jump#=5
Time=MilliSecs()
GX#=0
GY#=-1
GZ#=0
JX#=0
JY#=1
JZ#=0

Repeat
 
			PhysicsTime#=(MilliSecs()-Time)/1000.00 	 		
			If KeyDown(205) 
				TurnEntity Character,0,-AngularV#*PhysicsTime#,0
			End If
			If KeyDown(203)
				TurnEntity Character,0,AngularV#*PhysicsTime#,0
			End If 
			If KeyDown(200)
				Thrust#=5.0
 			Else
				Thrust#=0
			EndIf 
			C=CountCollisions(Character)
			If C
			VY#=0
				For Index=1 To C
					If CollisionNY#(Character,Index)>.5
					 AlignToVector Character,CollisionNX#(Character,Index),CollisionNY#(Character,Index),CollisionNZ#(Character,Index),2,.2
 					End If 

				Next 
			End If 
			
			If KeyHit(57) And C=True
			JumpX#=JX#*Jump#
			JumpY#=JY#*Jump#
			JumpZ#=JZ#*Jump#
			Vx#=Vx#+JumpX#
		 	Vy#=Vy#+JumpY#
			Vz#=Vz#+JumpZ#
			End If 
				  
			TFormNormal 0,0,1,Character,0	
			Thrust_NX#=TFormedX()
			Thrust_NY#=TFormedY()
			Thrust_NZ#=TFormedZ()
			
		  	ThrustVectorX#=Thrust_NX#*Thrust#
			ThrustVectorY#=Thrust_NY#*Thrust#
 			ThrustVectorZ#=Thrust_NZ#*Thrust#

			Vx#=Vx#+(ThrustVectorX#*PhysicsTime#)+(GX#*Gravity#*PhysicsTime#)
		 	Vy#=Vy#+(ThrustVectorY#*PhysicsTime#)+(GY#*Gravity#*PhysicsTime#)
			Vz#=Vz#+(ThrustVectorZ#*PhysicsTime#)+(GZ#*Gravity#*PhysicsTime#)
								
			Speed# = Sqr(Vx#^2 + Vy#^2 + Vz#^2) 
			Direction_X# = Vx# / Speed# 
			Direction_Y# = Vy# / Speed# 
			Direction_Z# = Vz# / Speed# 
					
			Speed# = Speed# - (Friction# * PhysicsTime#) 

			If Speed# < 0 Then Speed# = 0 

			;Vx# = Direction_X# * Speed#  
			;Vy# = Direction_Y# * Speed#  
			;Vz# = Direction_Z# * Speed#  

 
 
			
			TranslateEntity Character, Vx#*PhysicsTime#,Vy#*PhysicsTime# , Vz#*PhysicsTime# 
		
	 
			Time = MilliSecs()
			If Time > F_time Then
				F_Time = Time + 1000
				FPS = Fcount
				fcount = 0
			Else
				fcount = fcount + 1
			End If
	
	Update_Camera(PhysicsTime#)
	 
	UpdateWorld	
	RenderWorld  
	   
	Flip
	     
Until KeyHit(1)



sswift(Posted 2004) [#48]
I can't tell what is going wrong just by looking at it. Make a demo I can actually run by creating a sphere on a plane, and then I can debug it.

Ps:
Vx#=Vx#+(ThrustVectorX#*PhysicsTime#)+(GX#*Gravity#*PhysicsTime#)
Vy#=Vy#+(ThrustVectorY#*PhysicsTime#)+(GY#*Gravity#*PhysicsTime#)
Vz#=Vz#+(ThrustVectorZ#*PhysicsTime#)+(GZ#*Gravity#*PhysicsTime#)

Even though you CAN combine equations, it doesn't mean you should. In the long run you'll be better off if you don't. If you want to disable gravity later, or change how gravit ybehaves... or any number of things... you'll be better off keeping your equations simple, and seperate and adding all forces seperately.


Eric(Posted 2004) [#49]
Good Advice..

I actually combined them just before I sent my code..go figure.

Anyhow, When I get home, I will send you a copy of the code that you can run.

Best Regards,
Eric

BTW Where are you located? I am in Pennsylvania.


sswift(Posted 2004) [#50]
New Hampshire.

I drove through Pennsyvania once. The highlights of my tour were a neverending highway with no sign of civilization in sight, torrential downpours, and Amish people eating at a Dennys.


Eric(Posted 2004) [#51]
hahahahh How True that is... :) I work in a town that is 30 mins from home, and is predominately Amish. 95 Degrees, 95% humitity and their riding a bike in a heavy weight full length dress. I don't know how they do it.


Eric(Posted 2004) [#52]
Shawn,

Here is the Code.. Please forgive the sloppyness




sswift(Posted 2004) [#53]
I found the problem.

The problem is when your car first starts out it is not moving, so Vx# Vy# Vz# are 0.

As a result, speed is calculated to be 0, which is fine, but the car has no direction of travel. Since Vx# / 0 = NaN, Direction becomes NaN.

Then, the code you commented out tries to convert speed and direction back into a vector, but when it does this, it multiples speed by NaN, which results in the vector becoming NaN, which then screws up all future caclulations.

The solution is to check when you convert from a vector to a speed and direction whether speed is 0 or not.

Like so:

Speed# = Sqr(Vx#^2 + Vy#^2 + Vz#^2)

If Speed# > 0
Direction_X# = Vx# / Speed#
Direction_Y# = Vy# / Speed#
Direction_Z# = Vz# / Speed#
Else
Direction_X# = 0
Direction_Y# = 0
Direction_Z# = 0
EndIf


If it is 0, you set direction to a safe value. Any value will do really, so we choose 0.

In my own code, I do things a little differently. Instead of doing this check, what I do is I check to see if speed is 0 before I do my friction calculations. If it is, I skip them. There is no reason to check to see if the ship has slowed down any if it's speed is already 0. And adding thrust does not require you to convert your vector to a speed and direction.

So perhaps you should do that instead of what I suggested above. Calculate the speed before you do friction... you can skip the direction calculation... and then only do the friction calculations if the speed is greater than 0.


Eric(Posted 2004) [#54]
Ok, It's all working now... Thanks for all your help.
I choose to only Calc The Direction if my Speed not Zero.

Now I am going to attempt. Inclines. Right now, My character goes up and down them fine, I align him using The collision method you recommend. What My goal is, is depending on the angle of incline he will slid back down.

Thanks Again,
Eric


sswift(Posted 2004) [#55]
There's one more thing you need to do. And you need to check speed for this too. Which is why I suggested you check that once anread of doing ti a bunch of seperate times. :-)

I don't have time to explain this in detail, but basically, this is how you make an object bounce off the level. And you must do this, or else every second the object sits on the ground it is acceleratin downward from gravity, and just gaining energy that will make it stick to the ground even when you try to jump.

To make this work you need to get the collision normal between the object and the level. This is a simple way to do that but might not work well for multiple objects in Blitz. You'll have to get someoen else to help you fix up the collision code to make it robust, I ahven't got a ready made solution for that.

Anyhow, once you knwo the collision normal, you then can calculate the reflection angle given the angle the object was moving when it hit, and the angle of the surface. Then the object will bounce off the surface. Or it will just sit on the ground and not move, and NOT build up lots of downward momentum while it sits there, as gravity is canceled out each frame.

	; If the entity collided with the level, make it bounce.
			If Entity_Hit > 0 

				; Calculate bounce:

	    			; Get the normal of the surface which the entity collided with.    
					Nx# = CollisionNX(ballpos, 1)
					Ny# = CollisionNY(ballpos, 1)
					Nz# = CollisionNZ(ballpos, 1)
		
				; Compute the dot product of the entity's motion vector and the normal of the surface collided with.
					VdotN# = Vx#*Nx# + Vy#*Ny# + Vz#*Nz#
							
				; Calculate the normal force.
					NFx# = -2.0 * Nx# * VdotN#
					NFy# = -2.0 * Ny# * VdotN#
					NFz# = -2.0 * Nz# * VdotN#

				; Add the normal force to the direction vector.
					Vx# = Vx# + NFx#
					Vy# = Vy# + NFy#
					Vz# = Vz# + NFz#



Btw, there's your dot product. :-)


Eric(Posted 2004) [#56]
With my original code, I lied I can go up inclines but not down, it seems like I get stuck when I turn down hill.

any Ideas


Eric(Posted 2004) [#57]
Shawn,

Are you still there?

I need one last piece of advice. About my question above.. It refers to the code you evaluated for me.

Regards,
Eric

BTW Your bounce code works well, Thanks

Eric


sswift(Posted 2004) [#58]
I'll need to see a demonstration program to tell you what's wrong there. There should be no issue with going downhill, unless perhaps when you specified the collision mode, you specified the one that does not allow sliding downhill. But you should not have to turn that on to be able to walk down hills. So make a demonstration program.


Eric(Posted 2004) [#59]
I have no way to link to a program, It there a place that I can send it to you?


sswift(Posted 2004) [#60]
My email address, which is in my profile.


Eric(Posted 2004) [#61]
I sent the File, Please let me know if it made it.


sswift(Posted 2004) [#62]
Yes I got it I will look at it when I have the time.


Eric(Posted 2004) [#63]
OK Thanks.


sswift(Posted 2004) [#64]
I checked your code. Your problem is that you are applying thrust only when the player is colliding with the ground.

When the player walks down a hill, they make a series of small bounces, so every other frame they may not be colliding with the ground. This causes them to slow down a bit because no thrust is being applied.

To correct for this, if you want to apply thrust only when the player is colliding with the ground, then store the state of the last frame or two as far as collisions go, and if the player collided with the ground in the last three frames, then consider them as currently colliding with the ground for the purpouses of applying thrust.

You may also wish to do this for the purpouses of applying ground friction as well. Apply it if the player collided in any of the last three frames. That way if they bounce slightly they won't speed up from ground friction being disabled momentarily.


Eric(Posted 2004) [#65]
Amazing!! I will do that As Soon as I get home.

I am also working on a Space shooter, If I take away the Gravity# Most of this code will work for the Ship.
This little training course has been very helpful and very appreciated.

Regards,
Eric