• Entity - Sliding back to (0,0,0)?
    3 replies, posted
So, I've been working on this for a little while now, but I've come to a fairly obvious roadblock (that I knew was coming) and I'm curious how to get around it. If I add a velocity as per the set acceleration rate, the deltatime before I can do another calculation will throw me past the point I would like to reach (0,0,0) This code causes the entity to rotate flawlessly, but it will begin to reach zero, and will actually get to around 1 degree before it realizes that if it continues to accelerate, it will overshoot, and it settles at around 3.75 degrees. This is obviously due to how it was created (check if the distance from the acceleration is suitable, work with that), but this is obviously undesirable. My question is fairly straightforward - Is there a simple math equation that can do this, or the entire series of calculations for me? In a simplified sense, this is designed to do roughly the same thing as a spring equation. Return the tilt to zero as quickly as possible. However, the deceleration in this is linear, while the deceleration in a spring is exponential. That's primarily what I'm looking for here. And here's the code. I realize it's highly over-simplified, but it's really just an example. Ironically, if deltatime were infinitely small, this would work just fine. Using my limited research skills, I believe this is the difference between continuous and discrete-time equations? [code] function ENT:PhysicsSimulate(phys, deltatime) phys:Wake() local MaxSpeed = 5000 local AccelSpeed = 500 local DesiredAngle = Angle(0,0,0) DesiredAngle = self.Entity:WorldToLocalAngles(DesiredAngle) local AngularVel = phys:GetAngleVelocity() //Raw Angle Diff: DesiredAngle.y local CurSpeed = AngularVel.z local AccelDiff = AccelSpeed * deltatime local DesSpeed = 0 if DesiredAngle.y <= 0 and DesiredAngle.y >= -180 then DesSpeed = -500 elseif DesiredAngle.y <= 180 and DesiredAngle.y > 0 then DesSpeed = 500 end //Desired Speed is DesSpeed - The max velocity. If I took out the stuff below, it would actually just oscillate. local NxtSpeed = math.Approach(CurSpeed, DesSpeed, (AccelSpeed * deltatime)) local SpeedDif = NxtSpeed - CurSpeed local DecelDesSpeed = 0 local DecelNxtSpeed = math.Approach(CurSpeed, DecelDesSpeed, (AccelSpeed * deltatime)) local DecelSpeedDif = DecelNxtSpeed - CurSpeed local Mass = phys:GetMass() local TimeToStopCur = math.abs(CurSpeed / AccelSpeed) local TimeToStopNxt = math.abs(NxtSpeed / AccelSpeed) local DistToStopCur = 0.5 * (AccelSpeed / deltatime) * (TimeToStopCur ^ 2) //Distance to Stop Currently = DistToStopCur local DistToStopNxt = 0.5 * (AccelSpeed / deltatime) * (TimeToStopNxt ^ 2) //Distance To Stop After Acceleration = DistToStopNxt local DistToStop = math.abs(DesiredAngle.y) local ReturnForce = Vector(0,0,0) if DesiredAngle.y <= 0 and DesiredAngle.y >= -180 then if DistToStopNxt <= DistToStop then ReturnForce.z = AccelDiff * -1 * Mass //Accelerating Positively elseif DistToStopNxt >= DistToStop then ReturnForce.z = AccelDiff * Mass //Decelerating Negatively end elseif DesiredAngle.y <= 180 and DesiredAngle.y > 0 then if DistToStopNxt <= DistToStop then ReturnForce.z = AccelDiff * Mass //Accelerating Negatively elseif DistToStopNxt >= DistToStop then ReturnForce.z = AccelDiff * -1 * Mass //Decelerating Positively end end local ZeroVector = Vector(0,0,0) return ReturnForce, ZeroVector, SIM_LOCAL_FORCE [/code]
[b][url=http://wiki.garrysmod.com/?title=PhysObj.ComputeShadowControl]PhysObj.ComputeShadowControl [img]http://wiki.garrysmod.com/favicon.ico[/img][/url][/b] :devil:
[QUOTE=Crazy Quebec;21113915][B][URL="http://wiki.garrysmod.com/?title=PhysObj.ComputeShadowControl"]PhysObj.ComputeShadowControl [IMG]http://wiki.garrysmod.com/favicon.ico[/IMG][/URL][/B] :devil:[/QUOTE] Is there the code behind that floating around somewhere? Otherwise, I can't use it, because I haven't been able to apply any forces other than that. Also, I believe it's really just a spring-damper equation, not really ideal for what I'm trying to do.
Okay, so I've managed to put together a spring equation that does almost exactly what I want. Accuracy is excellent (< 1/4 degree), but there is a minor problem at higher spring constants (They control the acceleration rate). The object "jitters" slightly due to a high change in velocity, and compensation. This should be due to the fact that the spring applies either a fully positive force or a fully negative force. The damping force can then control the movement of the object, but deltatime is back, and it causes the object to rotate slightly before deltatime can contain it. At lower accelerations, this is not a problem, because the distance rotated is very small, and thus unnoticeable. However, at higher accelerations the distance travelled is much greater. Is there any way to fix this, or will I have to make the force change with distance? Presumably a shadow control takes the deltatime into account somehow when doing this type of equation, but I don't know how? [code] local DesiredAngle = Angle(0,0,0) DesiredAngle = self.Entity:WorldToLocalAngles(DesiredAngle) local AngularInertia = phys:GetAngleVelocity() local SpringConstantMaster = 1000 local SpringConstantx = SpringConstantMaster / (math.abs(DesiredAngle.r / 90)) local SpringConstanty = SpringConstantMaster / (math.abs(DesiredAngle.p / 90)) local SpringConstantz = SpringConstantMaster / (math.abs(DesiredAngle.y / 90)) local DesiredDampingCoef = 1 local DampingCoefx = DesiredDampingCoef * 2 * (math.sqrt(Mass * SpringConstantx)) local DampingCoefy = DesiredDampingCoef * 2 * (math.sqrt(Mass * SpringConstanty)) local DampingCoefz = DesiredDampingCoef * 2 * (math.sqrt(Mass * SpringConstantz)) local SpringForce = Vector(0,0,0) SpringForce.x = math.Clamp(DesiredAngle.r * SpringConstantx, -100000, 100000) SpringForce.y = math.Clamp(DesiredAngle.p * SpringConstanty, -100000, 100000) SpringForce.z = math.Clamp(DesiredAngle.y * SpringConstantz, -100000, 100000) local SpringForceDamp = Vector(0,0,0) SpringForceDamp.x = math.Clamp(AngularInertia.x * DampingCoefx * -1, -90000, 90000) SpringForceDamp.y = math.Clamp(AngularInertia.y * DampingCoefy * -1, -90000, 90000) SpringForceDamp.z = math.Clamp(AngularInertia.z * DampingCoefz * -1, -90000, 90000) SpringForce.x = SpringForce.x + SpringForceDamp.x SpringForce.y = SpringForce.y + SpringForceDamp.y SpringForce.z = SpringForce.z + SpringForceDamp.z local ReturnAngle = SpringForce local ZeroVector = Vector(0,0,0) return SpringForce, ZeroVector, SIM_LOCAL_FORCE [/code]
Sorry, you need to Log In to post a reply to this thread.