/// <summary> /// Most tight bounds for the rotational movement of the given point. /// </summary> /// <param name="point"></param> /// <param name="rotation"></param> /// <returns></returns> public static idBounds FromPointRotation(Vector3 point, idRotation rotation) { if (idMath.Abs(rotation.Angle) < 180.0f) { return(BoundsForPointRotation(point, rotation)); } else { float radius = (point - rotation.Origin).Length(); // FIXME: these bounds are usually way larger idBounds result = new idBounds(); result.Min = new Vector3(-radius, -radius, -radius); result.Max = new Vector3(radius, radius, radius); return(result); } }
public static idBounds BoundsForPointRotation(Vector3 start, idRotation rotation) { Vector3 end = start * rotation; Vector3 axis = rotation.Vector; Vector3 origin = rotation.Origin + axis * (axis * (start - rotation.Origin)); float radiusSqr = (start - origin).LengthSquared(); Vector3 v1 = Vector3.Cross(start - origin, axis); Vector3 v2 = Vector3.Cross(end - origin, axis); idBounds result = new idBounds(); // if the derivative changes sign along this axis during the rotation from start to end. if (((v1.X > 0.0f) && (v2.X < 0.0f)) || ((v1.X < 0.0f) && (v2.X > 0.0f))) { if ((0.5f * (start.X + end.X) - origin.X) > 0.0f) { result.Min.X = idMath.Min(start.X, end.X); result.Max.X = origin.X + idMath.Sqrt(radiusSqr * (1.0f - axis.X * axis.X)); } else { result.Min.X = origin.X - idMath.Sqrt(radiusSqr * (1.0f - axis.X * axis.X)); result.Max.X = idMath.Max(start.X, end.X); } } else if (start.X > end.X) { result.Min.X = end.X; result.Max.X = start.X; } else { result.Min.X = start.X; result.Max.X = end.X; } if (((v1.Y > 0.0f) && (v2.Y < 0.0f)) || ((v1.Y < 0.0f) && (v2.Y > 0.0f))) { if ((0.5f * (start.Y + end.Y) - origin.Y) > 0.0f) { result.Min.Y = idMath.Min(start.Y, end.Y); result.Max.Y = origin.Y + idMath.Sqrt(radiusSqr * (1.0f - axis.Y * axis.Y)); } else { result.Min.Y = origin.Y - idMath.Sqrt(radiusSqr * (1.0f - axis.Y * axis.Y)); result.Max.Y = idMath.Max(start.Y, end.Y); } } else if (start.Y > end.Y) { result.Min.Y = end.Y; result.Max.Y = start.Y; } else { result.Min.Y = start.Y; result.Max.Y = end.Y; } if (((v1.Z > 0.0f) && (v2.Z < 0.0f)) || ((v1.Z < 0.0f) && (v2.Z > 0.0f))) { if ((0.5f * (start.Z + end.Z) - origin.Z) > 0.0f) { result.Min.Z = idMath.Min(start.Z, end.Z); result.Max.Z = origin.Z + idMath.Sqrt(radiusSqr * (1.0f - axis.Z * axis.Z)); } else { result.Min.Z = origin.Z - idMath.Sqrt(radiusSqr * (1.0f - axis.Z * axis.Z)); result.Max.Z = idMath.Max(start.Z, end.Z); } } else if (start.Z > end.Z) { result.Min.Z = end.Z; result.Max.Z = start.Z; } else { result.Min.Z = start.Z; result.Max.Z = end.Z; } return(result); }
/// <summary> /// Most tight bounds for the rotational movement of the given bounds. /// </summary> /// <param name="idBounds"></param> /// <returns></returns> public static idBounds FromBoundsRotation(idBounds bounds, Vector3 origin, Matrix axis, idRotation rotation) { idBounds result = idBounds.Zero; Vector3 point = Vector3.Zero; float radius; if (idMath.Abs(rotation.Angle) < 180.0f) { result = BoundsForPointRotation(Vector3.Transform(bounds.Min, axis) + origin, rotation); point = Vector3.Zero; for (int i = 1; i < 8; i++) { point.X = (((i ^ (i >> 1)) & 1) == 0) ? bounds.Min.X : bounds.Max.X; point.Y = (((i >> 1) & 1) == 0) ? bounds.Min.Y : bounds.Max.Y; point.Z = (((i >> 2) & 1) == 0) ? bounds.Min.Z : bounds.Max.Z; result += BoundsForPointRotation(Vector3.Transform(point, axis) + origin, rotation); } } else { point = (bounds.Max - bounds.Min) * 0.5f; radius = (bounds.Max - point).Length() + (point - rotation.Origin).Length(); result = new idBounds(); result.Min = new Vector3(-radius, -radius, -radius); result.Max = new Vector3(radius, radius, radius); } return(result); }
public static idBounds BoundsForPointRotation(Vector3 start, idRotation rotation) { Vector3 end = start * rotation; Vector3 axis = rotation.Vector; Vector3 origin = rotation.Origin + axis * (axis * (start - rotation.Origin)); float radiusSqr = (start - origin).LengthSquared(); Vector3 v1 = Vector3.Cross(start - origin, axis); Vector3 v2 = Vector3.Cross(end - origin, axis); idBounds result = new idBounds(); // if the derivative changes sign along this axis during the rotation from start to end. if(((v1.X > 0.0f) && (v2.X < 0.0f)) || ((v1.X < 0.0f) && (v2.X > 0.0f))) { if((0.5f * (start.X + end.X) - origin.X) > 0.0f) { result.Min.X = idMath.Min(start.X, end.X); result.Max.X = origin.X + idMath.Sqrt(radiusSqr * (1.0f - axis.X * axis.X)); } else { result.Min.X = origin.X - idMath.Sqrt(radiusSqr * (1.0f - axis.X * axis.X)); result.Max.X = idMath.Max(start.X, end.X); } } else if(start.X > end.X) { result.Min.X = end.X; result.Max.X = start.X; } else { result.Min.X = start.X; result.Max.X = end.X; } if(((v1.Y > 0.0f) && (v2.Y < 0.0f)) || ((v1.Y < 0.0f) && (v2.Y > 0.0f))) { if((0.5f * (start.Y + end.Y) - origin.Y) > 0.0f) { result.Min.Y = idMath.Min(start.Y, end.Y); result.Max.Y = origin.Y + idMath.Sqrt(radiusSqr * (1.0f - axis.Y * axis.Y)); } else { result.Min.Y = origin.Y - idMath.Sqrt(radiusSqr * (1.0f - axis.Y * axis.Y)); result.Max.Y = idMath.Max(start.Y, end.Y); } } else if(start.Y > end.Y) { result.Min.Y = end.Y; result.Max.Y = start.Y; } else { result.Min.Y = start.Y; result.Max.Y = end.Y; } if(((v1.Z > 0.0f) && (v2.Z < 0.0f)) || ((v1.Z < 0.0f) && (v2.Z > 0.0f))) { if((0.5f * (start.Z + end.Z) - origin.Z) > 0.0f) { result.Min.Z = idMath.Min(start.Z, end.Z); result.Max.Z = origin.Z + idMath.Sqrt(radiusSqr * (1.0f - axis.Z * axis.Z)); } else { result.Min.Z = origin.Z - idMath.Sqrt(radiusSqr * (1.0f - axis.Z * axis.Z)); result.Max.Z = idMath.Max(start.Z, end.Z); } } else if(start.Z > end.Z) { result.Min.Z = end.Z; result.Max.Z = start.Z; } else { result.Min.Z = start.Z; result.Max.Z = end.Z; } return result; }
/// <summary> /// Most tight bounds for the rotational movement of the given bounds. /// </summary> /// <param name="idBounds"></param> /// <returns></returns> public static idBounds FromBoundsRotation(idBounds bounds, Vector3 origin, Matrix axis, idRotation rotation) { idBounds result = idBounds.Zero; Vector3 point = Vector3.Zero; float radius; if(idMath.Abs(rotation.Angle) < 180.0f) { result = BoundsForPointRotation(Vector3.Transform(bounds.Min, axis) + origin, rotation); point = Vector3.Zero; for(int i = 1; i < 8; i++) { point.X = (((i ^ (i >> 1)) & 1) == 0) ? bounds.Min.X : bounds.Max.X; point.Y = (((i >> 1) & 1) == 0) ? bounds.Min.Y : bounds.Max.Y; point.Z = (((i >> 2) & 1) == 0) ? bounds.Min.Z : bounds.Max.Z; result += BoundsForPointRotation(Vector3.Transform(point, axis) + origin, rotation); } } else { point = (bounds.Max - bounds.Min) * 0.5f; radius = (bounds.Max - point).Length() + (point - rotation.Origin).Length(); result = new idBounds(); result.Min = new Vector3(-radius, -radius, -radius); result.Max = new Vector3(radius, radius, radius); } return result; }
/// <summary> /// Most tight bounds for the rotational movement of the given point. /// </summary> /// <param name="point"></param> /// <param name="rotation"></param> /// <returns></returns> public static idBounds FromPointRotation(Vector3 point, idRotation rotation) { if(idMath.Abs(rotation.Angle) < 180.0f) { return BoundsForPointRotation(point, rotation); } else { float radius = (point - rotation.Origin).Length(); // FIXME: these bounds are usually way larger idBounds result = new idBounds(); result.Min = new Vector3(-radius, -radius, -radius); result.Max = new Vector3(radius, radius, radius); return result; } }
public TraceResult RotationModel(Vector3 start, idRotation rotation, idClipModel model, Matrix traceModelAxis, ContentFlags contentMask, int modelHandle, Vector3 modelOrigin, Matrix modelAxis) { idConsole.Warning("TODO: idClip.RotationModel"); // TODO: idTraceModel traceModel = TraceModelForClipModel(model); _rotationCount++; // TODO: return idR.CollisionModelManager.Rotation(start, rotation, traceModel, traceModelAxis, contentMask, modelHandle, modelOrigin, modelAxis); return new TraceResult(); }
public bool Rotation(out TraceResult result, Vector3 start, idRotation rotation, idClipModel model, Matrix traceModelAxis, ContentFlags contentMask, idEntity passEntity) { idConsole.Warning("TODO: idClip.Rotation"); /*idTraceModel traceModel = TraceModelForClipModel(model); idBounds traceBounds = new idBounds(); TraceResult traceResult; if((passEntity == null) || (passEntity.Index != idR.EntityIndexWorld)) { // test world _rotationCount++; // TODO: NEED ENGINE SOURCE idR.CollisionModelManager.Rotation(out result, start, rotation, traceModel, traceModelAxis, contentMask, 0, Vector3.Zero, Matrix.Identity); result.ContactInformation.EntityIndex = (result.Fraction != 1.0f) ? idR.EntityIndexWorld : idR.EntityIndexNone; if(result.Fraction == 0.0f) { return true; // blocked immediately by the world } } else { result = new TraceResult(); result.Fraction = 1.0f; result.EndPosition = start; result.EndAxis = traceModelAxis * rotation.ToMatrix(); } if(traceModel == null) { traceBounds = idBounds.FromPointRotation(start, rotation); } else { traceBounds = idBounds.FromBoundsRotation(traceModel.Bounds, start, traceModelAxis, rotation); } idClipModel[] clipModelList = GetTraceClipModels(traceBounds, contentMask, passEntity); foreach(idClipModel touch in clipModelList) { if(touch == null) { continue; } if(touch.RenderModelHandle != -1) { continue; } _rotationCount++; // TODO: traceResult = idR.CollisionModelManager.Rotation(start, rotation, traceModel, traceModelAxis, contentMask, touch.Handle, touch.Origin, touch.Axis); if(traceResult.Fraction < result.Fraction) { result = traceResult; result.ContactInformation.EntityIndex = touch.Entity.Index; result.ContactInformation.ID = touch.ID; if(result.Fraction == 0.0f) { break; } } } return (result.Fraction < 1.0f);*/ result = new TraceResult(); return false; }