Showing posts with label physics. Show all posts
Showing posts with label physics. Show all posts

Sunday, 11 June 2023

React Physics 3D : First Impressions

With my home engine coming to the state of being able to visually represent a world and move about within it, I've decided to set about sorting out a physics representation.

Very much as I did with the mathematics where I set about writing all my own code and then adopting a library; in order to best learn the process from first principles I also set about writing my own physics engine and visualizer (the latter using the much more familiar to me fixed function pipeline of DirectX 9 - Yes it still has a use in 2023!)

The physics implementation I went with was a simple rigid body test for cuboids and spheres.  Then a ray cast.  At which point I set about seeking a library as it's a huge topic I didn't want to sink too much time into.

I settled, after about a fortnight of reading and trying on React Physics 3D.

My initial impressions are that it is easy to set up, supports CMake and just worked; though I'm yet to fully get to grips with it, I am happy I have my world and simulation set up and working.

I've also happily separated my game objects from my visual objects with the use of my Ecs and I'm able to do the same, by registering a new Ecs update system with my entity list and simply piping the commands to create and destroy physics objects per frame.

The update pumping of time matches my engine instantly, so I had a lot of wins.

However, I am not building in a permissive manner, I have maximum warnings as errors, I have strictness on and permissive off; I also remove all compiler specific extensions, so I am using only C++ in it's rawest, most portable form.

Immediately, even though I've compiled React separately and then just link to the library statically, I have a bunch of the React headers giving me errors; notably map, BroadPhaseSystem and DefaultLogger.

The first two are the same sort of issue, which just surprised me, there's a constexpr uint64 set to minus one (so it's max) an unsigned value set to a signed negative to under roll it... Well it's quite bad practice:

static constexpr uint64 INVALID_INDEX = -1;

And I immediately updated this to:

static constexpr uint64 INVALID_INDEX { std::numeric_limits<uint64_t>::max() };

I may feed this back to the author, he most likely knows, maybe there's even a reason for it, personally I'd always stick to numeric limits and max in this case though, not least as it is constexpr and not a hack ;) 

The other one was a lambda expression in a call to std::transform for making all logging strings lower case, the code simply used ::tolower.  However, it was not type safe, it was converting int to char, but that's not explicit and so I changed it over to read:

std::string toLowerCase(const std::string& text) {
                std::string textLower{ text };
                std::transform(textLower.begin(), textLower.end(), textLower.begin(), [](const char& character) -> char { return static_cast<char>(std::tolower(character)); });
                return textLower;
            }

The lambda here is hard to read, so lets split it out:

[](const char& character) -> char 
{
    return static_cast<char>(std::tolower(character));
}

We take in a character, return a character, explicitly, so we have to cast the int return of std::tolower... simple really, but hard to read.  It compiles down well; but just using "::tolower" well that's a decay to int and you have to be permissive in your type exchange... I don't like that, express yourself in your code type correctly, and it'll be type safe.

Sunday, 5 February 2023

Physics Debugger in my Home Game Engine

It may not look much, but this is a huge step forward in my home game engine development.  This is a physics visualization tool I've written, to show me the shapes I register with my physics simulation, it communicates with the game client one frame behind the client, and lets me zoom a camera around the world to see whether shapes line up and to take a snapshot of the physics/collisions being resolved this frame.

The whole physics system is pretty much a bag of spatial checks at the moment, for instance I ray cast from a given point to the four corners of a cube to test whether the point is within, that's pretty compute-intensive.

But at least now I can see there is only one such cube (the purple/pink) one in the scene.

I can also clearly see the ground mesh (the yellow/red triangles).

Infinity is just the blue.


Also, this rendering of the physics world is using yet another renderer I've put together, again integrating ImGui as my defacto GUI in such circumstances.

I need to do a lot of work on this, but it's just a fun project.

And recently having a bit of run, something you can tinker with, something which just makes you think and relax is perhaps key to improving ones skills.

Before I started this whole home game engine (despite working on games at work) I had no idea how to put a renderer together; even as badly as I have; and certainly no idea about a physics engine, now I have the rough knowledge of both.

My home project backing up my experience at work, and also the home project lets me try things I might not otherwise do at work, like totally break things... Oh no wait, I break things all the time....

Sunday, 1 August 2021

My Home Game Engine - Motion Decay (Physics) Bug

A few of you may have noted I've been writing my own graphics engine at home, this has fast become my own home game engine; which is more or less just a play ground for me play about with.

And over the weekend I've started to flesh out the physics engine, beginning with a physically reactive camera.  I want to make this thing tilt and shake and move like it's organic, not on the end of your keyboard or mouse.

The motif is going well.

I designed a head for many edge cases I expected, one of them being floating point in accuracy and so I built two things into the movement, first a dead-zone, so zero isn't the ONLY value which doesn't move the camera, instead an area of 0.0004 around the camera forms a null - don't move - zone for all my motion calculations.

And the second was the force of friction or wind resistance, this is just called "Decay" in my engine, you decay from moving to  no longer moving.  Because wind, water or surface friction are going to come into play at different times and from different directions on each object.

Anyway, do work out the motion which needs applying to any object I build a vector of motion actions, these themselves are stored in a set of efficient constexpr static arrays per object type; for not I have so few object types this is fine, it leads to faster code (one day, if I have more than ten moving object types I may need to revisit this.

Alas, this smartness immediately bit me in the arse... And I just spent nearly half an hour pawing over the wrong piece of code to figure out why when switching to an object known to be at rest (0, 0, 0) with no actions on it... it'd slowly jiggle backwards at a very slow rate.

I checked my maths, my direction vectors, my initialization of the actual speed of the object, everything checked out.  I made sure I was giving no inputs, so I wasn't landing in the accelerate or decelerate motion actions.

So I was properly confused, I took a moment and I re-read the code I'd done yesterday (oh the difference a day makes) and suddenly I realized I had two kinds of decay... if you're moving forward you slow down... and if you're moving backwards you also slow down... both heading to zero, or at least the 0.0004 null zone.

Other objects were not moving, just this one particular type... and having a quick squizz, sure enough the acceleration and deceleration decay were BOTH being applied, even at rest this object would jump to a speed and start to decay, this would then swing it below -0.0004 in the null zone and the deceleration decay would kick in... and the deceleration was MORE than the acceleration so then the object was trying to decelerate a little but more each third frame... zero to backwards to null zone to backwards to nullzone... on and on, tiny increments.

This was a flat out bug, the decay should have only been applied to make the object come to, but not beyond the nullzone.

However, I was still perplexed how the forward decay was being applied, sure enough it is, in the above call to "GetMotionActions" we can see it's both ForwardSpeedDecay and BackwardSpeedDecay are "valid" motion actions for objects receiving no input.

And they'd been doing this all the time, every frame... the specialty of this one particular object?  Just the numbers, the profile for motion, specifically the braking, was a larger number taking it beyond nullzone.  And this is multipled by delta time for the frame... all following frames are small, short, but the first frame?... or a frame after a break point... HUGE....

In short I made a bunch of mistakes, but I learned, and I enjoyed myself.  This is perhaps the key thing when trying something new.

I also have a healthy appreciation for just taking a physics engine off of the shelf having done some of this ground work - and I'm literally just playing.