I've decided to revisit my old Physics code.
This time I'll be disregarding the old framework for arbitrary geometries, at first.
I want to concentrate on the most simple geometry (sphere), and I want to look deeper into things I barely touched apon, such as arbitrary contraints.

The major difference in the framework will be the very clear distinction between a collision body, and a dynamic body.

A collision body is a 3D geometry which supports detection of collisions. It has a shape, it supports velocity, but not mass, and has no way to RESPOND to a collision. An example of this : missiles that explode apon contact.

A dynamic body is a derivation of the collision body - it does everything a collision body does, but it has mass, and it can respond to a collision. Do I have to give examples? Look around you.

The new engine will handle both of these, in context.

Stand by for my first code... especially if all the stuff I posted in the past made no sense to you!
Posted on 2008-12-09 02:49:36 by Homer

I still really like the idea of using Spheres to perform the 'broad phase' collision testing.
The Bullet physics engine uses 'axially aligned bounding boxes' (aabb's) for this, and I think its a bad idea. Why?
Rotating objects need to have their aabb calculated for every frame, and worse than that...
If we need to search within the current timestep for the moment of impact, the aabb of a rotating object will be constantly changing, and need to be calculated once for each moment of time at which we apply an instantaneous test for intersection... this means extracting eight constantly changing vertices, and performing a series of point/plane tests, whereas a sphere is just a single test.

Spheres don't change shape, and can be used in a 'swept test' to quickly determine whether a sphere is remotely likely to collide with something during the current timestep, and if so, can tell us the time at which a sphere will make 'first contact' - ie, the moment of impact.
If the object is in fact NOT a sphere (ie, is merely using a sphere to perform rough testing), we can then search the timestep using the actual geometry, and beginning at the sphere impact time (rather than the beginning of the timestep), potentially speeding up that search by several orders.

It's also worth noting that the swept sphere test will work for objects moving at high velocity, whereas the more expensive aabb test can fail to detect high-speed collisions, and that means things that are moving fast can potentially fly straight through walls and each other, which really doesn't look very professional.
If we detect a sphere collision, we will often still need to perform some secondary testing using a better geometric approximation, which we call 'narrow phase' collision detection - but we would always need to do this for anything that is not actually sphere shaped.

Although I won't be implementing any other geometries at first, it's nice to know that the Sphere code is useful for GENERAL broad-phase collision testing of ARBITRARY geometries... we can write a single broadphase collision detector, and a geometry-specific narrow phase detector to find the exact moment of impact.

Basically, we want to create a list of pairs of objects which will collide during the timestep, figure out which collision is going to occur first, wind the simulation forward to that time, resolve that collision, search the list for any other mentions of those two bodies and re-evaluate those collisions, then find the next earliest collision in the list and repeat this until the list is exhausted. We're probably still not at the end of the current timestep, but thats ok, we can continue simulating from the most advanced moment of impact we could find.

Posted on 2008-12-09 21:51:31 by Homer
You can find references to 'sphere sweep test' on Google, if you are interested, but if we forget about the math for a moment, what we're really doing is 'extruding' two Spheres in the direction of their velocities, creating two 'capsules' (cylinders with half-spheres on the end caps), and checking whether they intersect (I like to imagine them as Light Sabers clashing in the darkness).
Although the spheres may not be moving linearly (most things move in curves), for the duration of a single timestep we can consider the motion to be linear, and so we can use a linear equation to solve the problem.
Mathematically, we can express the problem as a Quadratic Equation, which is a linear equation.

Anyway, enough about this, the basic elements we need to get a small demo together are just these:
- CollisionBody class, describing the most simple collidable object.
- Simulator class, which contains and drives the simulated objects, and knows about Time.

In the next few posts I'll describe these classes, using as little code as possible.
We can add stuff to them later, when we require it.
But I'd like to walk through the building of a physics engine from the ground up, so I'll try hard not to jump ahead too much.

Posted on 2008-12-10 02:02:50 by Homer
The most important data type we'll use in physics is called a 3D Vector.
You might imagine this as a three dimensional arrow - it points in one direction, and it has a length - but we can also use a Vec3 to describe things like 'Position in World space', which isn't so obviously a 'pointing' thing, but if I said 'draw an arrow from the origin of the universe to a given point in space', we can see that position can also be thought of in terms of an arrow.

We'll define a 3D Vector using a structure like this:

Vec3 struct
X real4 ?
Y real4 ?
Z real4 ?
Vec3 ends

We can see that the Vec3 struct describes three floating-point values, which define its direction and magnitude.
In this case, I've defined the three fields as 32-bit values, but that decision is arbitrary, they could be 64-bit (real8), or any other size, depending on the accuracy that you require.
If you can't understand what a Vec3 is, then you have absolutely no chance of understanding this thread, so I would suggest that you try to figure out what the heck this thing is NOW, before blundering onwards.

In order to simulate the physical state of a set of collidable bodies, we're going to need to describe the physical state of a SINGLE body ... in fact, we need to define TWO physics states for each body - the 'current' state, and the 'next' state (ie, the state NOW, and the state after some time has passed).
So let's define the most simple Physical State using another structure:

;This struct describes the minimal physical State for collision checking.
;Note that this describes a physical body 'without mass',
;although 'CM' refers to the Center of Mass of the object, which is ASSUMED to be its Origin.
state struct
CMPosition Vec3 <>          ;Position in world space
CMVelocity Vec3 <>          ;Rate of change of Position
Orientation Mat33 <>        ;rotation matrix, bodyspace to worldspace
CMAngVel   Vec3 <>          ;Rate of change of orientation
state ends

Can we make sense of this?
Position is pretty obvious and doesn't require explaining.
(Linear) Velocity can be thought of as 'speed and direction' - it describes which direction the object is moving in, and at what rate. It's important to know that velocity describes the RATE OF CHANGE OF POSITION... to find the "new position", we'll multiply the velocity by some amount of Time, and then add the "old position".
Orientation is described as a 3x3 matrix, which is just one way that we can describe rotation. Other people have other ideas about which is the 'best' way to do this, but this is the one I'm using.
ANGULAR Velocity describes the RATE OF CHANGE OF ORIENTATION - its telling us how fast the object is spinning, and around which 3D axis. I won't be going too deeply into the Rotation side of things for a while, so don't panic too much, but what the heck is a Mat33?

Mat33 struct
m00 real4 ?
m01 real4 ?
m02 real4 ?
m10 real4 ?
m11 real4 ?
m12 real4 ?
m20 real4 ?
m21 real4 ?
m22 real4 ?
Mat33 ends

DirectX uses 'row major order', and OpenGL uses 'column major order'.
Since I mainly work with DirectX, I'll stick to that format..
A 3x3 matrix, in 'row major order', looks like this:

m00 m01 m02
m10 m11 m12
m20 m21 m22

We could think of it as three Vec3's (m00 m01 m02) (m10 m11 m12) (m20 m21 m22)

Again, its not really important to us yet, so lets leave it alone... ok, just one more thing to say about Mat33, THEN we'll leave it alone (for now)..
If we fill the matrix so that the diagonal from top left to bottom right contains ONE, and the rest contains ZERO, its called an IDENTITY MATRIX - and this means "no change" - for a Mat33, being used to describe a rotation, it means "no rotation"... the Identity Matrix for a 3x3 matrix would be:

1.0  0  0
0    1.0  0
0    0  1.0

Now we have described the most important data elements that we'll use in physics simulation, we can go on to describe the basic collidable body... we already know that it needs two States, but there's a few other things it will need too, in my next post we can take a good look at that, then we can begin looking at the simulator.

Posted on 2008-12-10 03:01:57 by Homer
Here's an early version of the CollisionBody class.
This class describes a 3D geometric object that supports collision detection, but not collision resolution - we can tell when one of these smacks into something, but we can't make it bounce off. Later I'll introduce a new class derived from this one that DOES support collision response.

We can see the two State structs that I mentioned, and a few other data members.
Since I am going to start with the most simple 3D geometric primitive (sphere), there is a field to define the Radius of a sphere.
dShapeID is used to determine what geometric shape the body is, so later we can define more shapes.
IsAwake is a boolean which we can use to put bodies to sleep when they are no longer moving, we can do less computations for sleeping bodies.
m44_BodyToWorld is a 4x4 transformation matrix, similar to the Mat33 we saw previously
We can combine a rotation and a translation in a single Mat44, and use it to draw our 3D object correctly when we get around to that (I mean, 3D stuff is not much fun if you can't see it on the screen, is it?)
We'll learn about the Mat44 later, when we need to.

Now on to the Methods of this Class.
The Init method sets the shape id, and doesn't do much else.
CreateSphere is used to initialize the object as a Sphere.
BroadSweep is used to perform broadphase collision detection of 'this' object with another object.
It will use some kind of Sweep algorithm, such as 'sphere/sphere sweep', depending on what kind of objects we are dealing with.
Get_Closing_And_Relative_Velocities does what it says.. these values are required for sweep tests.
The Closing Velocity is the speed two objects have, relative to each other, as a single floating point value.
That means it doesn't have a direction as such, although its Sign tells us if the objects are approaching one another or moving apart from one another.
Relative Velocity is a Vec3, it tells us the actual direction of the closing velocity, as taken from one object with respect to the other.
Don't worry if these concepts sound alien, you can find much better descriptions of them at your leisure.
For now, we just need to know that they are useful for performing sweep tests.

I won't be providing code for any of these Methods today, I think it's better that I show the two most important class definitions first, then start providing code. So here is the CollisionBody class, and next post will contain the Simulator class. Please note that these classes are not complete, and will be subject to change as we need more stuff it will be added.

;The CollisionBody class describes a collidable object.
;It has linear and angular velocity (3D speed and spin), but has NO Mass-related properties,
;and cannot RESOLVE collisions, only DETECT them.
Object CollisionBody, 82124, Shape
RedefineMethod Init, Pointer, dword
VirtualMethod  CreateSphere, Pointer, real4, real4, BOOL
VirtualMethod  Get_Closing_And_Relative_Velocities, Pointer

;Physical State
DefineVariable OldState, state, {<>}   ;physical state, with no 'Mass' stuff
DefineVariable NewState, state, {<>}

DefineVariable dShapeID, dword, SHAPEID_UNDEFINED  ;describes the shape of the 3D geometry
DefineVariable IsAwake,BOOL,FALSE   ;Sleeping objects cannot 'cause' a collision
DefineVariable m44_BodyToWorld, Mat44, {<>}   ;rotation & translation (no scaling or shear)

ObjectEnd

Posted on 2008-12-11 01:23:03 by Homer
Here's a very rough class definition for the Simulator.
The most important thing to note is the embedded collection to hold arbitrary bodies.
This class does not merely DRIVE the simulated bodies, it CONTAINS them - it's a container.

We can see that the simulator supports Gravity and Damping.
I think we all know what Gravity is - well, I hope so!
Damping is a mechanism for removing energy from moving bodies.
It's a way to guarantee that bodies will eventually settle down and stop moving, in the absence of external forces acting on them.
As with the CollisionBody class, we can expect this class to grow and change.. this is merely a stripped-down version of my old physics simulator class, I've removed things like 'springs' from it, because I intend to support a much wider variety of 'constraints' than I had previously.

I won't talk more about the methods in this object at this time, as I would be skipping too far ahead for some people, but we'll get to that as soon as we've looked at the CollisionBody methods in more detail.
Once we've outlined the methods for both object classes, we will be ready to put together a very rough demo - the first demo won't have any 3D rendering code, it will just emit text messages to let us see that values are changing over time. If the output looks sane, we'll put together a graphical demo so we can see things on the screen.

Object PhysicsSimulator, 83453, Streamable

RedefineMethod Init,                                Pointer, real4
RedefineMethod Done
VirtualMethod ToggleGravity
VirtualMethod ToggleDamping
VirtualMethod Update,                                real8
VirtualMethod ComputeForces
VirtualMethod Simulate,                                real8
VirtualMethod Integrate,                                real8
VirtualMethod CheckCollisions,                        real8
VirtualMethod FindExactCollisionTime,                Pointer, Pointer, real8, real8, Pointer

DefineVariable DampingActive,                        BOOL,TRUE
DefineVariable GravityActive,                        BOOL,TRUE

Embed Bodies,        Collection

ObjectEnd

I think 60 views of this thread in three days is encouraging (given the number of hits this site receives per day), obviously this is a popular topic, and I hope I can make this information as easy to understand as possible - physics people tend to write for other physics people, keeping this stuff close to their chest, and making it seem much more complicated than it really is. I think that there is something of a superiority complex amongst many of them, they treat this field as a private club, and I think that is deplorable and despicable, and ultimately, it is self destructive as it isolates them from the rest of us, it marginalizes them, and that is the road to obscurity and thus oblivion. Science is not just for scientists, physics is not just for physicists, computers are not just for programmers - we all live in the same reality, we are all subject to its laws.

Posted on 2008-12-11 02:40:23 by Homer
Physics does not need to be hard.
Let's ignore rotation for now, and just think about linear velocity and position.

The simulation depends very much apon Time, and the most simple physics simulators divide time into relatively small 'timesteps', for example one tenth of a second (0.1 seconds).
The main job of the simulator is to advance the state of the simulated bodies.
Given the 'old' state of a body, and the elapsed amount of Time, we can calculate the 'new' state of a body.

The most simple formula in physics is used to move our body in linear space according to its linear velocity.
Given that V = linear velocity, and T = the elapsed Time, and P = the position of the body, we can calculate the change of position as follows:

dP = V * T ... the change in position equals velocity multiplied by elapsed time.

To find the new Position, we need to take the old Position into account...
newP = dP + oldP

Calculating the new state from the old state with respect to Time is called "Integration" (and also, "numerical integration").
The above formula gives us enough knowledge to write a very simple "integrator" method for our simulator that can make our simulated bodies move linearly - this formula describes "Euler Integration" after the man who invented it.
As mentioned previously, most things really move in curves, not linearly, and so there are many improved algorithms based on Euler's work, most notably "RK4" (Runge Kutta fourth order numerical integration).
Sounds complex, but it's actually not difficult to implement, I'll show you how at a later date.

Anyway, I think we have enough to write a very, very simple Integration method for our simulator which will change the positions of the bodies according to their velocity.
I know that I'm jumping the gun a little bit here, but it's very important to understand how to turn those nasty physics formulas into working code - the implementation of a concept!
Stand by for the code for this most important method, we'll get something that we can compile as soon as possible, and then build on that.
Posted on 2008-12-11 05:51:30 by Homer
obviously this is a popular topic

Yup, it is ^^

I wonder if you've seen Nvidia's PhysX and would like to hear your opinion on this one, if possible? Nvidia claims that PhysX enables super-accurate physics simulation with minimal coding effort and they advertise it by showing how it uses hardware acceleration on "GeForce 200"-series cards. Is this really our future or kinda worthless crap given that the modern CPUs don't have anythig to do, because GFX cards handle like 95% of the rendering process..?
Posted on 2008-12-11 11:25:14 by ti_mo_n
I've had a bit of a play around with PhysX - and let me tell you, unless you are running a physics accelerator in hardware, it's utter garbage.
The only thing that makes it remotely appealing to developers is that it is easily portable across a number of popular platforms.

Basically, PhysX (in software) is so slow that you are quite limited in the number of objects that can be simulated - in order to hide this inadequacy, the demos that ship with PhysX just have objects disappearing when a certain count (a couple of hundred) is reached - even when simulating something as simple as spheres with a dozen or so collision surfaces to bounce and roll apon. Simply having objects disappearing is quite alarming to me, where did they go? What happened to them? This completely destroys any suspension of disbelief - I would rather see objects 'glitching' than simply ceasing to exist !!

Further confirmation of the low quality of this engine can be found in the list of games (and game developers) who currently support it... my, what an obscure bunch, have never heard of most of them, with the notable exception of Atari, who for all intents and purposes (at least in terms of game development) are DECEASED (their Melbourne, Australia office, whom they acquired as part of their acquisition of long-term game developer Melbourne House, and which was their worldwide headquarters for gamedev, is now registered to Infogrames).
PhysX just simply is not fast enough for anything but lightweight applications, I'm sure it will appeal to some developers, but no 'serious' developer would use this engine.

Believe me, in terms of a purely software solution, the Bullet engine is miles (and miles) ahead, is several orders faster (and supports MANY more objects), is open-sourced, has attracted a whole bunch of contributing authors from around the world, and is free for commercial use (PhysX requires a license for commercial purposes).
In fact, Walt Disney Studios have just used Bullet in their new movie, and have posted their Bullet plugin for Maya on the Bullet forum (which already had its own physics engine that is too slow and not very feature rich).
I think that is a glowing recommendation for using Bullet.

Having said all of that, Bullet is far from efficient due to its determination to be all things to all users... in my opinion, it's a little bit over-engineered in that pretty printing and proper structure are given priority over its purported goal of sheer speed and believability. This is probably a little unfair of me, since I am really judging C++ against ObjAsm32, where we can introduce a lot of cheats and shortcuts (such as directly accessing the data elements of an object rather than using lots of 'Get' and 'Set' methods). But the bottom line is this: even though Bullet is well-regarded as one of the fastest and most robust engines around, it's easily possible to improve its speed by several orders.

Ultimately my biggest complaint against Bullet is that it is poorly documented, and contains barely any useful comments - you're forced to trawl through the web forum in order to understand any part of its internals.
It's not really aimed at people who wish to understand physics simulation and implement their own - it doesn't teach anything useful, it's 'prug and pray' code for lazy developers who must then whine on the forum about why things don't work the way they expected, and hope they get a response that makes sense, even though they don't have the fundamental knowledge or understanding to modify the code for themselves.

Posted on 2008-12-12 00:31:29 by Homer
Time to start putting this baby together... today we'll be working on the PhysicsSimulator class methods.
I'm going to disregard the Init method (aka constructor method) for the moment, as its quite boring.
Instead, let's start by looking at the method which we call from our main program loop in order to drive the simulator. For now, all code will be stripped down, so we won't worry about collisions or anything else, just the nuts and bolts.

In our main loop, we obtain the elapsed time, using the high performance timer.
Then we call the Update method, which advances the simulation in discrete timesteps.
The Update method calls the Simulate method once for each discrete timestep.
This means that the physics might be updated several times for each rendered frame.
For example, if 302 ms have elapsed, and the timestep is set to 100ms (0.1 seconds), then the Update method will call the Simulate method three times, and add the remaining 2ms to an internal accumulator.

;Advances the physics simulation by one TimeStep for each TimeStep that has elapsed.
;This method decouples rendering from physics in regards to Time.
;Your application should call this from its main loop,
;it's your entrypoint to drive the simulation.
Method PhysicsSimulator.Update,uses esi,deltaTime:real8
SetObject esi
.if .Bodies.dCount==0
ExitMethod
.endif

;Accumulator = Accumulator + deltaTime
fld  deltaTime                    ;Add the deltaTime to the Accumulator
fstp PhysicsTimeAccumulator
.repeat

fld  PhysicsTimeAccumulator
fsub  PhysicsTimeStep
fstpReg eax
.if eax!=0 && eax!=80000000h
.ifBitSet eax,BIT31                        ;accumulator < timestep
;DbgWarning "not time yet"
.break    ;Do nothing, its not time yet
.endif
.endif

OCall Simulate                          ;Advance the simulation by one TimeStep
fchs                                        ;counter = counter - consumed
fstp PhysicsTimeAccumulator

.until 0

MethodEnd

The Simulate method does a few things.
#1 - it calculates the current 'internal forces' of all bodies.
#2 - it calculates the 'new' state of all bodies b
#3 - (disabled) check for and resolve all Collisions
#4 - switches the 'old' and 'new' states of all bodies.

;This method will attempt to advance the simulation by DeltaTime.
Method PhysicsSimulator.Simulate,uses esi
SetObject esi

;calculate Force and Torque (due to current linear momentum, and gravity)
OCall ComputeForces

;Integrate our system forward
OCall Integrate, PhysicsTimeStep

;Here's where we would perform collision detection and resolution
;....

;Swap the States
OCall SwapStates

MethodEnd

Now we've seen the two functions which drive our simulation, we just need a little bit of code for the new methods that have been mentioned, and we can build a very primitive simulator - it won't do much except advance the simulation, and move bodies linearly according to their velocity.
So a couple more posts and we'll have enough to build our first test program :)
Posted on 2008-12-12 03:13:38 by Homer
Just a little remark: if you use a decent compiler infrastructure, get* and set* methods should be inlined, giving effectively the same speed as directly accessing the data. With a system that supports link-time code generation, it works even when the getters and setters are defined at .cpp scope instead of the header file.

Other than that, I'm just lurking, and looking forward to a demo simulation I can play with ^_^
Posted on 2008-12-12 06:05:11 by f0dder
Biterider has, at my request, implemented 'inline methods' in OA32, so I can write those ugly Get and Set methods and not pay for them... but I still prefer just simple directly accessing the data, the inline methods are only to make things easier on the casual reader. Although they appear to be 'real methods', they compile as inline code... pretty much as you described.
Posted on 2008-12-12 06:33:18 by Homer
For a lot of stuff getters and setters are sorta irrelevant anyway, apart from "it's good programming style". I still do prefer using them though, since they can offer nice debugging hooks, can ensure invariants are satisfied, make it easier to add caching if necessary, etc. And since simple getters/setters get optimized into simple data access, there isn't much reason not to use them :)

If we look aside from the software implementation and focus only on the hardware acceleration, how well does PhysX do? Significantly faster than software-only solutions? My GF8800 should supposedly support HW PhysX acceleration, but all the recent nvidia drivers cause BSOD on startup on my system, so I can't play around >_<
Posted on 2008-12-12 06:43:58 by f0dder
I have an 8800 card too - this card does not sport a physics coprocessor, no - the claim is that much of the physics math can be offloaded onto the gpu, which is true - but this is at the cost of visual effects (shaders suffer), and that's really not much of a tradeoff.
Please note that the GF8800 is 'CUDA-friendly' - and that CUDA is just nvidia's proprietary version of GPGPU.
Even with gpu assisted processing, the PhysX engine is not that great... perhaps they should evaluate their algorithms rather than trying to offload the processing work onto the graphics processor?
It would be better if the physics engine supported some kind of load-balancing, where the workload was processed on the device which was least busy at the time..
Unfortunately, I can't tell you how well PhysX does on cards that DO support a true physics coprocessor, but I can say that has very little to do with the PhysX engine anyway!
Posted on 2008-12-12 07:23:11 by Homer
I'm beginning to suspect that some (if not most) of the list of game developers using PhysX are startup companies which are indirectly owned by nvidia - this is just an exercise in self promotion, where are the benchmarks? They benchmark everything else. I think the demos that they ship with it tell the real story.
Posted on 2008-12-12 22:35:45 by Homer
I have an 8800 card too - this card does not sport a physics coprocessor, no
AFAIK none of the GeForce cards have PPUs, but execute physics code on the GPU. Again, AFAIK, it's only supported on the 8xxx series and upwards since that's the first GPU that's generic (and powerful) enough to support it?

Even with gpu assisted processing, the PhysX engine is not that great... perhaps they should evaluate their algorithms rather than trying to offload the processing work onto the graphics processor?
If it isn't all that fast, that would probably be an idea :)

It would be better if the physics engine supported some kind of load-balancing, where the workload was processed on the device which was least busy at the time..
I wonder how well that would work? A GPU is supposed to be orders of magnitudes faster at stuff like physics processing than a standard CPU?

Unfortunately, I can't tell you how well PhysX does on cards that DO support a true physics coprocessor, but I can say that has very little to do with the PhysX engine anyway!
The PhysX PPU was discontinued after nvidia bought up the company, and I haven't heard anything about integrating a discrete PPU on their graphics cards?
Posted on 2008-12-13 07:49:19 by f0dder
I just found some benchmarks on the 9600gt and upwards... 3 to 4 times faster than the cpu - considering that gpu operations can be easily coded to be 4x parallel, this is no suprise at all.... I mentioned in another thread that the gpu can be used to accelerate many kinds of conventional processing through parallel operation, and I was told I was an idiot... there you go.
Still, that assumes that we don't want to use the gpu for the purpose for which it was intended!
Posted on 2008-12-13 11:38:48 by Homer
GPUs are still not fast enough to draw almost-movie-quality stuff onscreen, they are high-latency, and PC drivers+interfaces(GL/DX) add too much overhead. Few have SLI, so a multicore solution sounds nicer to me :).
That said, I have only a GF8600GT+ C2D E4600 and the physx-nvidia demos running at 15fps were not charming.
Posted on 2008-12-13 13:08:07 by Ultrano
In order to write our physics simulator, we'll need some building blocks.
I've said that the most common data that we'll work with is in the form of 3D vectors.
Attached is a small set of macros for performing vector math operations using FPU code and real4 accuracy.
This file contains the most important / common math ops, but there will be others that we'll require, and so this file will be extended as we need them.

Posted on 2008-12-13 20:49:03 by Homer
Here's our earliest testbed project - it includes the maths, collisionbody and simulator.
The application doesn't really do anything, but it compiles, and all the code for linear motion is in place.
Hey, it's a start :)

Please study the code provided, and ask any questions that you feel need to be asked at this time.
Also, note that MASM and ObjAsm32 are both REQUIRED to build this project - and the RadASM IDE is RECOMMENDED - but you can still study the code even if you don't have these.

As I keep saying, all these files are subject to change, and updates will be made available as I continue this work.
If you have suggestions, or notice any lurking bugs, or you feel like writing MMX versions of the math functions, please let me know in this thread!!
Posted on 2008-12-13 22:21:33 by Homer