Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

803 Good

1 Follower

About bmarci

  • Rank

Personal Information


  • Twitter

Recent Profile Visitors

6486 profile views
  1. This might be an old paper, but I've been using this approach for many years, and still loving it http://www.peroxide.dk/papers/collision/collision.pdf The sample code is an excellent start and quite robust, as I remember.
  2. bmarci

    Limited Slip Differential Modelling

    Well yes, actually it "doesn't matter" if you split the locking torque in half or not, just results in different behaviour, sometimes it's hard to tell just by eyeball I do it, by the way. Also as I figured (couldn't get it confirmed by a professional, though) that the locking is not just instant, as the wedges move, the clutches get pressed against each other...etc. so it's more like a gradual thing, and you cannot relay only on whether it's locked or not. There is a state when it's "getting locked" So what I did was, using the current bias ratio to weight the wheel torques, until they get locked. Something like this; t_locking0 = (t_preload + abs(bias_ratio - curr_ratio) * (t0 - t1)) * 0.5 t_preload = preload torque of the diff bias_ratio = the diff's pre-defined torque bias ratio curr_ratio = the current ratio of the wheels' feedback torque (always >1) t0, t1 = feedback torques from the wheels t_locking0 = the torque transferred to the (first) wheel, the other wheel gets the same with opposite sign The most simple way of doing that is something used in early racer (http://racer.nl/) If you have a driveline component class which can be literally anything that rotates, and have your diff and wheels derived from that, you can simply just have references (pointers) to those components in your diff setup. This way the outputs of a diff can be either a wheel, or an other diff, doesn't matter as long as it has SetAngularVelocity() or GetFeedbackTorque()...etc functions
  3. bmarci

    Limited Slip Differential Modelling

    That's the torque that the diff can not handle, half of it will go to one wheel, the other half to the other wheel with opposite sign. I'm not 100% sure if not the whole goes to the wheel with less resistance, I'll have to check it up It's quite hard to tell, and it depends on the friction of the clutch or whatever locking mechanism the diff uses. If you want to calculate the torque that brings the 2 wheels at the same speed, is not that difficult after all; ang_acc = torque / inertia target_ang_vel = current_ang_vel + ang_acc * dt Here you know everything except the torque, so reordering the equation can give you the amount of torque you are looking for. Something like: torque = ((target_ang_vel - current_ang_vel) * inertia) / dt You can target to the average speed. The only difficulty I see here is you have to simulate one step to get the current speed of the wheel before you apply locking torque. Having applied that the wheel speed changes and that "invalidates" the tire forces and almost every parameters that you have just calculated I haven't tried this method yet, though, maybe it works Probably this is why most of us "cheat" by using a single state variable for locking and modify the wheel velocity by hand, like it was a simple fixed axle.
  4. bmarci

    Limited Slip Differential Modelling

    That's the point, when the LSD is locked it acts as a fixed axle, and that's it. When the TBR and preload are exceeded it starts acting as an open diff, and from the torque differences and preload you can calculate some torques I may already referred to this page, but who knows, maybe not: http://www.racer.nl/tutorial/differentials.htm I'd still vote on this one.
  5. bmarci

    Limited Slip Differential Modelling

    The viscous never locks. The viscous coefficient is a sort of viscosity resistance of the oil in the "device". No physical meaning simulation wise. You can imagine it as this number increases the thickness of the oil in the coupling increases And yes, if you choose a big enough number it can act as fully locked, but in practice it'll just generate too much locking torque (locking is a bad terminology here) that overshoots and the whole simulation becomes unstable/exploding if you are not lucky. I'm pretty sure AC is dealing with many kind of diffs, but only @kunos can confirm that In AWD/4WD usually viscous is the most common choice. If you define your diff as one input and two outputs, you can handle the middle diff as 2 other diffs connected to it's output instead of 2 wheels. You still have torques and angular velocities, technically no difference Actually that torque never leaves the differential, so when you have a slippy and sticky wheels, their axles start to rotate at different speeds. If there is a mechanism, like some fluid or clutches that act between the axles (inside the diff) that extra friction torque is what you are looking for. In my sim I only have spool and open diff, and some "extra" on top of them handling all LSD scenarios. I hope I helped clarifying instead of confusing
  6. bmarci

    Limited Slip Differential Modelling

    Hi, in case you haven't done that already, probably the viscous is the easiest to simulate. The diffTorque is calculated from the wheel's angular velocity difference and a coefficient value (some magic number) diffTorque = (rightAngVel - leftAngVel) * viscousCoeff * 0.5f; The *0.5f is because the total locking torque is split between the 2 axles. You can get quite far with only viscous diffs, but if you are keen on digging yourself into fancy stuff, this is a good read: http://www.intothered.dk/simracing/differential.html Also, it's quite difficult to simulate full locking with only torques. The good old method is to identify when it's fully locked and simulate it as fixed axle.
  7. bmarci

    Matrices - translation and rotation

    Haha, yes, true story Changing "undocumented" code that was made by a guy who left the company 10 years ago, and nobody has a clue what he had in mind when he made it, and it works perfectly but the game designers want some new feature As a side note: I think a most of the time a well optimized code is not too pleasant to look at I do it a lot, eg: most of my collision code works better in the object's local space. Also in my vehicle simulation, some of the physics is calculated in the vehicle's local space, some forces act in the wheel's space, then again a whole bunch of things come from world space, so I transform them back and forth all the time I suppose I could have been unified them into one space, but as well known equations and formulas are defined in a specific frame, and I wanted to understand the code 5-10 years later, I decided not to bother my tire formulas Exactly this is how I do it. Transforming vertices with quaternions is not that optimal. https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation They're compact in memory, then again when you have to calculate with them they can hit back As @alvaro mentioned, it's good for animation data, and transforming a quaternion with an other is faster than matrix-matrix multiply. I think we misunderstood each other, probably I expressed my idea in the wrong way The translation part is not that mysterious, I was thinking of, something let's say: You debug some code, and look at the rotation matrix as 9 numbers, you'd see something similar in the debugger: m[0] = [1, 0, 0] m[1] = [0, 0, 1] m[2] = [0, -1, 0] or even worse: m = [1, 0, 0, 0 , 0, 1, 0, -1, 0] Is Y pointing down or forward? Again, with my matrix represented as 3 vectors you'd see something: m.x = [1, 0, 0] m.y = [0, 0, 1] m.z = [0, -1, 0] No question here No big deal, just a little convenience.
  8. bmarci

    Matrices - translation and rotation

    Row vs column major! It always confuses me if I see a matrix and don't know which 3 numbers represent a certain direction. For me it's much more clear if I see a vector component in a transformation and I instantly know that points up in local space That's the point, I don't, I don't even want to care, I don't want "accidents", whenever I had to hunt for a bug, that has never been because I accidentally took a matrix in a wrong order In my vector thinking these kind of mistakes are simply not possible. Of course, if I have a matrix only for storage and I don't ever calculate anything with it, there is no point in separation. But most of the cases, even in AAA games, we had everything in 4x4 matrices because the sacred GPU likes that way, and the game code looked like a mess. Full with matrix decompose and inverses. But at least the engine/render guys could blame the game coders because the overall bad performance Somehow it works for me, and exactly that's what I'm doing with my rotate + translate combo, and before I pass it to the render I pack them into a 4x4 matrix. Yes, but why would I keep a copy if I can have everything at hand? With a pure 4x4 rotation matrix half of the operations will be multiplying numbers by zeros and adding them together. I agree. I haven't profiled it yet, though... As I saw in the past, the performance doesn't always depend on the 2x faster low level function. I try to keep everything as simple as possible, that always helped me in the valley of darkness If it's still not clear why that poor spaceship moves and rotates, I still believe the 3-vector rotation and position representation of a matrix is a good starting point
  9. bmarci

    Matrices - translation and rotation

    "Fortunately" I never learnt about matrices, I figured out a solution for rotating points that later turned out to be matrix multiplication. You can imagine it by having 3 unit vectors aligned to the major axes. If you want to rotate a point, just rotate those 3 vectors, and then combine the corresponding vector components with the point's in question. eg: take the X component of all the axis vectors and multiply them by the point's X component, and the sum will be the rotated X, and so on. res.x = mtx.x.x * pos.x + mtx.y.x * pos.y + mtx.z.x * pos.z; This is a 3x3 rotation matrix. And yes they are not just arbitrary 9 numbers or a 3x3 array of floats. They represent 3 vectors, each of them pointing along the corresponding axis. As long as they have unit length they simply rotate. And you can guess, if you scale the X axis by 2 that will result in scaling along X axis by 2 Thus, I never used the float[4][4] representation because they are a kind of meaningless pack of numbers for me. I use 3x3 rotation matrix, position and scaling separated. I've been using this format for more than 20 years and never had the idea to change If you want to use 4x4 matrices for other than rendering I'd encourage you not to do so. In the logic side they are just pain. For final rendering you must have a 4x4 matrix anyway, but from the format above you can combine it in no time, just copy the values at the right place in the 4x4 matrxix and you are done, and you have to do it probably once. If you look at a 4x4 matrix closely you can notice that the top-left 3x3 area is this rotation+scaling part. (3 scaled axis vectors) The last row/column (depending on your preference) is the translation (position) Just see an identity matrix: [ 1 0 0 0 ] [ 0 1 0 0 ] [ 0 0 1 0 ] [ 0 0 0 1 ] A matrix that rotates 90° around Y and moves 5 to the right(X), and 2 up (Y) : [ 0 0 -1 0 ] [ 0 1 0 0 ] [ 1 0 0 0 ] [ 5 2 0 1 ] In both matrices the bold numbers are the rotation vectors. If you expand the transformation for a 4x4 matrix by a vector[4] res.x = mtx.x.x * pos.x + mtx.y.x * pos.y + mtx.z.x * pos.z + mtx.w.x * pos.w; The last multiplication (bold) is the translation part, the rest is the rotation. I hope I didn't screw it up There are more benefits: You can never tell if a float[4][4] matrix is row or column major, and always a riddle how to get the "up" vector. If you don't put scale in the rotation and keep the position separated, you'll never need to decompose. eg: need a position 3meters in front of the camera? : pos = camera.mtx.z * 3 + camera.pos (I use Y-up because I'm old ) If you use orthogonal 3x3 rotation matrices, you can forget about matrix inverse. In 99% of the cases the matrix inverse results in simple transpose that is FREE compared to any SSE optimized fancy stuff. Most math libraries don't implement a multiply by transpose function, so you must rely on inverse. My representation is left-handed row-major, I use directx so I love it This is just a general purpose matrix, for projection you'll have to dig deeper. And of course this is just my personal taste, I'd guess most people would argue.
  10. As @Green_Baron mentioned, separating the force/torque calculation and integration is a good idea. In theory the order should not matter. But, since the brakes could lock up the wheels that could introduce some extra "fun" In normal circumstances you would not need to care about this at all. The free-rolling angular velocity is a derived value and has nothing to do with the simulation. Your others steps seem right to me. You only need the torques that change the speed of the wheel and don't have to zero the angular velocity! The torques only give you the angular acceleration that change the velocity in every frame. This might not be related, but at low speed you can expect some problems. The tire formula is designed to work at speed. Below around 5m/s it becomes "unstable". That shouldn't affect the overall movement of the car, but the angular velocity calculation gets problematic. Search for Tire relaxation length method or SAE950311, also there is a simpler way of doing it but I don't remember its name For me it looks like this: if (ground_seed < 1) slip_ratio = 2 * (wheel_speed - ground_speed) / (1 + ground_speed^2) else ... use normal slip ratio calculation...
  11. bmarci

    Turbocharger Implementation?

    Hello, a few years back the same topic popped up for me too. Check this thread out, it may help; https://www.gamedev.net/forums/topic/664785-car-physics-turbochargers-and-friends/?tab=comments#comment-5204207 I personally went for the simple model and didn't regret it
  12. Speed should be in m/s. Also yes it can go high. At higher speed the majority of slow-down factor comes from air resistance. In this case you would only accelerate the engine/flywheel. But as @marclurr wrote if you want the clutch to slip you need more sophisticated drivetrain simulation. The clutch could be a 0..1 value and you'd need the max torque that the clutch can deliver. Since the clutch can lock when the pedal is half way down, and also can slip even when you don't touch it (in extreme cases) So just multiply the pedal value by the clutch max torque, and if the torque coming from the engine is greater then it slips, otherwise it locks. The clutch is always trying to match the speed of the engine and the transmission. That means, if the clutch slips its friction torque slows down the engine and speeds up the wheels, and as soon as their speed "match" the clutch is locked. So to answer the original question the clutch is pressed, the max torque is 0. It only accelerates the flywheel, like; acc = GetEngineTorque(RPM) / FlywheelInertia EngineAngVel += acc * dt I feel some disturbance here. You are mixing the forces and torques which are not good friends in the same equation The engine torque goes to the wheels that generates wheel rotation that goes to the tire formula that gives friction force that you apply on the rigid body. The air resistance is a force that you have to apply directly on the body. The CG is a good start. In the video the resistance seems way too high!
  13. Yes, I've been trying to do the same, but I had to realize that it's not that simple sometimes. And that's why I separated the update into various steps. The physics only calculates the forces and torques and nothing more. And then I calculate the movements/rotations and CHEAT. Not exactly out of nothing. It comes from the locking mechanism (clutch, fluid...etc) but yes, it comes from the diff and only affects the wheels, never goes back to the engine AFAIK. In reality they are never locked, only torques play as you would expect. The only problem is we don't have infinite small update steps, but we have floating point precision issues in return And this is why we have to cheat sometimes. The viscous never "locks", that's a simple case. The LSD is a bit trickier, but only because you have to mimic the locking state when the timestep is not small enough to calculate it properly. Regarding diffs, you can go into the "deep forest", the question is whether you want to You can get away with spool, open, viscous, and LSD, and leave the rest. For a long time I didn't even have LSD because the viscous was so convincing
  14. Hi, A realistic way involves a lots of things, like clutch, gearbox, differentials and the tyre itself. I'd say you can map the 0-1 pedal input to a torque output that accelerates the whole thing. The RPM is kind of calculated value, a result of the simulation. Also the 10% throttle will not necessarily rev up to the maximum, just until the engine torque and the friction balances. As I saw in the video, your car is moving nicely, and it reminds me to my first fake driveline I made about 5-6 years ago. As I remember, I directly applied some acceleration on the wheels (depending on engine RPM, current gear and throttle position); Something like: ang_vel = FreeRollingAngVel() * magic_number the magic_number was a scaling value that increased/decreased the current rotation speed. Then I calculated the wheel speed back to the engine. Somehow it worked so convincing it took me years before I implemented the real thing For this specific case (engine with clutch disengaged). You have a throttle position 0..1 And the current engine RPM. You'll need an engine torque curve, that is the torque at a specific RPM at full throttle, this way you can query the output torque at the engine's current RPM. You can have an other curve for engine braking, but that's not that relevant now. So, you can simply multiply the looked up value by the throttle, or blend engine vs friction torque using the throttle position. Now you have the torque that accelerates the flywheel, for this you need the flywheel inertia, integrate it over time, and you are done. t_engine = GetEngineTorque(engine_rpm) t_brake = GetEngineBrakeTorque(engine_rpm) t = Lerp(t_brake, t_engine, throttle) // or just t = t_engine * throttle ang_acc = t / flywheel_inertia ang_vel += ang_acc * dt engine_rpm = AngVelToRPM(ang_vel) or something similar
  15. This could cause a lot of headache. You cannot tell (or not easy to tell) how much torque you need to apply to reach a certain speed. As it depends on the whole tire formula and brakes...etc. You have good chances that you just overshoot, and eventually the whole simulation explodes The best approach would be a kind of viscous diff like locking, but it'll never perfectly lock, but oscillate, and if you choose a fairly big coeff, it'll go out of control. You don't have to make a mess with torques and angular velocities. What worked for me was, separating the update to various steps. 1. Calculate the forces and torques 2. Integrate (this is the actual advance-in-time) 3. Derive In the first step you don't have to bother with time, only apply the formuals/equations...etc, and get forces/torques. The integration is the actual time-update, nothing to do with physics, just "animate" with previously calculated values. And finally calculate some "misc" values from the simulation. Here you can deal with speeds, RPMs...etc. Personally, I don't have this, I just do it at the end of the Integrate step
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!