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]
[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.