Newer
Older
bool lineCCrossing = AreLineSegmentsCrossing(linePoint1, linePoint2, rectC, rectD);
bool lineDCrossing = AreLineSegmentsCrossing(linePoint1, linePoint2, rectD, rectA);
Marco Zimmer
committed
if (lineACrossing || lineBCrossing || lineCCrossing || lineDCrossing)
{
Marco Zimmer
committed
return true;
}
Marco Zimmer
committed
else
{
Marco Zimmer
committed
return false;
}
}
Marco Zimmer
committed
else
{
Marco Zimmer
committed
return true;
}
}
Marco Zimmer
committed
//Returns true if "point" is in a rectangle mad up of RectA to RectD. The line point is assumed to be on the same
//plane as the rectangle. If the point is not on the plane, use ProjectPointOnPlane() first.
public static bool IsPointInRectangle(Vector3 point, Vector3 rectA, Vector3 rectC, Vector3 rectB, Vector3 rectD)
{
Marco Zimmer
committed
Vector3 vector;
Vector3 linePoint;
Marco Zimmer
committed
//get the center of the rectangle
vector = rectC - rectA;
float size = -(vector.magnitude / 2f);
vector = AddVectorLength(vector, size);
Vector3 middle = rectA + vector;
Marco Zimmer
committed
Vector3 xVector = rectB - rectA;
float width = xVector.magnitude / 2f;
Marco Zimmer
committed
Vector3 yVector = rectD - rectA;
float height = yVector.magnitude / 2f;
Marco Zimmer
committed
linePoint = ProjectPointOnLine(middle, xVector.normalized, point);
vector = linePoint - point;
float yDistance = vector.magnitude;
Marco Zimmer
committed
linePoint = ProjectPointOnLine(middle, yVector.normalized, point);
vector = linePoint - point;
float xDistance = vector.magnitude;
Marco Zimmer
committed
if ((xDistance <= width) && (yDistance <= height))
{
Marco Zimmer
committed
return true;
}
Marco Zimmer
committed
else
{
Marco Zimmer
committed
return false;
}
}
Marco Zimmer
committed
//Returns true if line segment made up of pointA1 and pointA2 is crossing line segment made up of
//pointB1 and pointB2. The two lines are assumed to be in the same plane.
public static bool AreLineSegmentsCrossing(Vector3 pointA1, Vector3 pointA2, Vector3 pointB1, Vector3 pointB2)
{
Marco Zimmer
committed
Vector3 closestPointA;
Vector3 closestPointB;
int sideA;
int sideB;
Marco Zimmer
committed
Vector3 lineVecA = pointA2 - pointA1;
Vector3 lineVecB = pointB2 - pointB1;
Marco Zimmer
committed
bool valid = ClosestPointsOnTwoLines(out closestPointA, out closestPointB, pointA1, lineVecA.normalized, pointB1, lineVecB.normalized);
Marco Zimmer
committed
//lines are not parallel
if (valid)
{
Marco Zimmer
committed
sideA = PointOnWhichSideOfLineSegment(pointA1, pointA2, closestPointA);
sideB = PointOnWhichSideOfLineSegment(pointB1, pointB2, closestPointB);
Marco Zimmer
committed
if ((sideA == 0) && (sideB == 0))
{
Marco Zimmer
committed
return true;
}
Marco Zimmer
committed
else
{
Marco Zimmer
committed
return false;
}
}
Marco Zimmer
committed
//lines are parallel
else
{
Marco Zimmer
committed
return false;
}
}
Marco Zimmer
committed
//This function calculates the acceleration vector in meter/second^2.
//Input: position. If the output is used for motion simulation, the input transform
//has to be located at the seat base, not at the vehicle CG. Attach an empty GameObject
//at the correct location and use that as the input for this function.
//Gravity is not taken into account but this can be added to the output if needed.
//A low number of samples can give a jittery result due to rounding errors.
//If more samples are used, the output is more smooth but has a higher latency.
public static bool LinearAcceleration(out Vector3 vector, Vector3 position, int samples)
{
Marco Zimmer
committed
Vector3 averageSpeedChange = Vector3.zero;
vector = Vector3.zero;
Vector3 deltaDistance;
float deltaTime;
Vector3 speedA;
Vector3 speedB;
Marco Zimmer
committed
//Clamp sample amount. In order to calculate acceleration we need at least 2 changes
//in speed, so we need at least 3 position samples.
if (samples < 3)
{
Marco Zimmer
committed
samples = 3;
}
Marco Zimmer
committed
//Initialize
if (positionRegister == null)
{
Marco Zimmer
committed
positionRegister = new Vector3[samples];
posTimeRegister = new float[samples];
}
Marco Zimmer
committed
//Fill the position and time sample array and shift the location in the array to the left
//each time a new sample is taken. This way index 0 will always hold the oldest sample and the
//highest index will always hold the newest sample.
for (int i = 0; i < positionRegister.Length - 1; i++)
{
Marco Zimmer
committed
positionRegister[i] = positionRegister[i + 1];
posTimeRegister[i] = posTimeRegister[i + 1];
}
positionRegister[positionRegister.Length - 1] = position;
posTimeRegister[posTimeRegister.Length - 1] = Time.time;
Marco Zimmer
committed
positionSamplesTaken++;
Marco Zimmer
committed
//The output acceleration can only be calculated if enough samples are taken.
if (positionSamplesTaken >= samples)
{
Marco Zimmer
committed
//Calculate average speed change.
for (int i = 0; i < positionRegister.Length - 2; i++)
{
Marco Zimmer
committed
deltaDistance = positionRegister[i + 1] - positionRegister[i];
deltaTime = posTimeRegister[i + 1] - posTimeRegister[i];
Marco Zimmer
committed
//If deltaTime is 0, the output is invalid.
if (deltaTime == 0)
{
Marco Zimmer
committed
return false;
}
Marco Zimmer
committed
speedA = deltaDistance / deltaTime;
deltaDistance = positionRegister[i + 2] - positionRegister[i + 1];
deltaTime = posTimeRegister[i + 2] - posTimeRegister[i + 1];
Marco Zimmer
committed
if (deltaTime == 0)
{
Marco Zimmer
committed
return false;
}
Marco Zimmer
committed
speedB = deltaDistance / deltaTime;
Marco Zimmer
committed
//This is the accumulated speed change at this stage, not the average yet.
averageSpeedChange += speedB - speedA;
}
Marco Zimmer
committed
//Now this is the average speed change.
averageSpeedChange /= positionRegister.Length - 2;
Marco Zimmer
committed
//Get the total time difference.
float deltaTimeTotal = posTimeRegister[posTimeRegister.Length - 1] - posTimeRegister[0];
Marco Zimmer
committed
//Now calculate the acceleration, which is an average over the amount of samples taken.
vector = averageSpeedChange / deltaTimeTotal;
Marco Zimmer
committed
return true;
}
Marco Zimmer
committed
else
{
Marco Zimmer
committed
return false;
}
}
Marco Zimmer
committed
Marco Zimmer
committed
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
//This function calculates angular acceleration in object space as deg/second^2, encoded as a vector.
//For example, if the output vector is 0,0,-5, the angular acceleration is 5 deg/second^2 around the object Z axis, to the left.
//Input: rotation (quaternion). If the output is used for motion simulation, the input transform
//has to be located at the seat base, not at the vehicle CG. Attach an empty GameObject
//at the correct location and use that as the input for this function.
//A low number of samples can give a jittery result due to rounding errors.
//If more samples are used, the output is more smooth but has a higher latency.
//Note: the result is only accurate if the rotational difference between two samples is less than 180 degrees.
//Note: a suitable way to visualize the result is:
Vector3 dir;
float scale = 2f;
dir = new Vector3(vector.x, 0, 0);
dir = Math3d.SetVectorLength(dir, dir.magnitude * scale);
dir = gameObject.transform.TransformDirection(dir);
Debug.DrawRay(gameObject.transform.position, dir, Color.red);
dir = new Vector3(0, vector.y, 0);
dir = Math3d.SetVectorLength(dir, dir.magnitude * scale);
dir = gameObject.transform.TransformDirection(dir);
Debug.DrawRay(gameObject.transform.position, dir, Color.green);
dir = new Vector3(0, 0, vector.z);
dir = Math3d.SetVectorLength(dir, dir.magnitude * scale);
dir = gameObject.transform.TransformDirection(dir);
Debug.DrawRay(gameObject.transform.position, dir, Color.blue); */
public static bool AngularAcceleration(out Vector3 vector, Quaternion rotation, int samples)
{
Marco Zimmer
committed
Vector3 averageSpeedChange = Vector3.zero;
vector = Vector3.zero;
Quaternion deltaRotation;
float deltaTime;
Vector3 speedA;
Vector3 speedB;
Marco Zimmer
committed
//Clamp sample amount. In order to calculate acceleration we need at least 2 changes
//in speed, so we need at least 3 rotation samples.
if (samples < 3)
{
Marco Zimmer
committed
samples = 3;
}
Marco Zimmer
committed
//Initialize
if (rotationRegister == null)
{
Marco Zimmer
committed
rotationRegister = new Quaternion[samples];
rotTimeRegister = new float[samples];
}
Marco Zimmer
committed
//Fill the rotation and time sample array and shift the location in the array to the left
//each time a new sample is taken. This way index 0 will always hold the oldest sample and the
//highest index will always hold the newest sample.
for (int i = 0; i < rotationRegister.Length - 1; i++)
{
Marco Zimmer
committed
rotationRegister[i] = rotationRegister[i + 1];
rotTimeRegister[i] = rotTimeRegister[i + 1];
}
rotationRegister[rotationRegister.Length - 1] = rotation;
rotTimeRegister[rotTimeRegister.Length - 1] = Time.time;
Marco Zimmer
committed
rotationSamplesTaken++;
Marco Zimmer
committed
//The output acceleration can only be calculated if enough samples are taken.
if (rotationSamplesTaken >= samples)
{
Marco Zimmer
committed
//Calculate average speed change.
for (int i = 0; i < rotationRegister.Length - 2; i++)
{
Marco Zimmer
committed
deltaRotation = SubtractRotation(rotationRegister[i + 1], rotationRegister[i]);
deltaTime = rotTimeRegister[i + 1] - rotTimeRegister[i];
Marco Zimmer
committed
//If deltaTime is 0, the output is invalid.
if (deltaTime == 0)
{
Marco Zimmer
committed
return false;
}
Marco Zimmer
committed
speedA = RotDiffToSpeedVec(deltaRotation, deltaTime);
deltaRotation = SubtractRotation(rotationRegister[i + 2], rotationRegister[i + 1]);
deltaTime = rotTimeRegister[i + 2] - rotTimeRegister[i + 1];
Marco Zimmer
committed
if (deltaTime == 0)
{
Marco Zimmer
committed
return false;
}
Marco Zimmer
committed
speedB = RotDiffToSpeedVec(deltaRotation, deltaTime);
Marco Zimmer
committed
//This is the accumulated speed change at this stage, not the average yet.
averageSpeedChange += speedB - speedA;
}
Marco Zimmer
committed
//Now this is the average speed change.
averageSpeedChange /= rotationRegister.Length - 2;
Marco Zimmer
committed
//Get the total time difference.
float deltaTimeTotal = rotTimeRegister[rotTimeRegister.Length - 1] - rotTimeRegister[0];
Marco Zimmer
committed
//Now calculate the acceleration, which is an average over the amount of samples taken.
vector = averageSpeedChange / deltaTimeTotal;
Marco Zimmer
committed
return true;
}
Marco Zimmer
committed
else
{
Marco Zimmer
committed
return false;
}
}
Marco Zimmer
committed
//Get y from a linear function, with x as an input. The linear function goes through points
//0,0 on the left ,and Qxy on the right.
public static float LinearFunction2DBasic(float x, float Qx, float Qy)
{
Marco Zimmer
committed
float y = x * (Qy / Qx);
Marco Zimmer
committed
return y;
}
Marco Zimmer
committed
//Get y from a linear function, with x as an input. The linear function goes through points
//Pxy on the left ,and Qxy on the right.
public static float LinearFunction2DFull(float x, float Px, float Py, float Qx, float Qy)
{
Marco Zimmer
committed
float y = 0f;
Marco Zimmer
committed
float A = Qy - Py;
float B = Qx - Px;
float C = A / B;
Marco Zimmer
committed
y = Py + (C * (x - Px));
Marco Zimmer
committed
return y;
}
Marco Zimmer
committed
//Convert a rotation difference to a speed vector.
//For internal use only.
private static Vector3 RotDiffToSpeedVec(Quaternion rotation, float deltaTime)
{
Marco Zimmer
committed
float x;
float y;
float z;
Marco Zimmer
committed
if (rotation.eulerAngles.x <= 180.0f)
{
Marco Zimmer
committed
x = rotation.eulerAngles.x;
}
Marco Zimmer
committed
else
{
Marco Zimmer
committed
x = rotation.eulerAngles.x - 360.0f;
}
Marco Zimmer
committed
if (rotation.eulerAngles.y <= 180.0f)
{
Marco Zimmer
committed
y = rotation.eulerAngles.y;
}
Marco Zimmer
committed
else
{
Marco Zimmer
committed
y = rotation.eulerAngles.y - 360.0f;
}
Marco Zimmer
committed
if (rotation.eulerAngles.z <= 180.0f)
{
Marco Zimmer
committed
z = rotation.eulerAngles.z;
}
Marco Zimmer
committed
else
{
Marco Zimmer
committed
z = rotation.eulerAngles.z - 360.0f;
}
Marco Zimmer
committed
return new Vector3(x / deltaTime, y / deltaTime, z / deltaTime);
}