/// <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> /// A fast, conservative center-to-corner culling test. /// </summary> /// <param name="bounds"></param> /// <param name="modelMatrix"></param> /// <param name="planeCount"></param> /// <param name="planes"></param> /// <returns>Returns true if the box is outside the given global frustum, (positive sides are out).</returns> public static bool RadiusCullLocalBox(idBounds bounds, Matrix modelMatrix, int planeCount, Plane[] planes) { if (idE.CvarSystem.GetInteger("r_useCulling") == 0) { return(false); } // transform the surface bounds into world space Vector3 localOrigin = (bounds.Min + bounds.Max) * 0.5f; Vector3 worldOrigin; LocalPointToGlobal(modelMatrix, localOrigin, out worldOrigin); float worldRadius = (bounds.Min - localOrigin).Length(); // FIXME: won't be correct for scaled objects for (int i = 0; i < planeCount; i++) { Plane frust = planes[i]; float d = frust.Distance(worldOrigin); if (d > worldRadius) { return(true); // culled } } return(false); // no culled }
/// <summary> /// Performs quick test before expensive test. /// </summary> /// <param name="bounds"></param> /// <param name="modelMAtrix"></param> /// <param name="planeCount"></param> /// <param name="planes"></param> /// <returns>Returns true if the box is outside the given global frustum, (positive sides are out).</returns> public static bool CullLocalBox(idBounds bounds, Matrix modelMatrix, int planeCount, Plane[] planes) { if (RadiusCullLocalBox(bounds, modelMatrix, planeCount, planes) == true) { return(true); } return(CornerCullLocalBox(bounds, modelMatrix, planeCount, planes)); }
public static idBounds operator +(idBounds a, idBounds b) { idBounds newBounds = new idBounds(); newBounds.AddBounds(a); newBounds.AddBounds(b); return(newBounds); }
public override bool Equals(object obj) { // FIXME: this is going to do boxing isn't it? check for performance. if (obj is idBounds) { idBounds b = (idBounds)obj; return((this.Min == b.Min) && (this.Max == b.Max)); } return(base.Equals(obj)); }
/// <summary> /// Tests all corners against the frustum. /// </summary> /// <remarks> /// Can still generate a few false positives when the box is outside a corner. /// </remarks> /// <param name="bounds"></param> /// <param name="modelMatrix"></param> /// <param name="planeCount"></param> /// <param name="planes"></param> /// <returns>Returns true if the box is outside the given global frustum, (positive sides are out).</returns> public static bool CornerCullLocalBox(idBounds bounds, Matrix modelMatrix, int planeCount, Plane[] planes) { // we can disable box culling for experimental timing purposes if (idE.CvarSystem.GetInteger("r_useCulling") < 2) { return(false); } Vector3 v = Vector3.Zero; Vector3[] transformed = new Vector3[8]; float[] distances = new float[8]; int i, j; // transform into world space for (i = 0; i < 8; i++) { v.X = ((i & 1) == 0) ? bounds.Min.X : bounds.Max.X; v.Y = (((i >> 1) & 1) == 0) ? bounds.Min.Y : bounds.Max.Y; v.Z = (((i >> 2) & 1) == 0) ? bounds.Min.Z : bounds.Max.Z; LocalPointToGlobal(modelMatrix, v, out transformed[i]); } // check against frustum planes for (i = 0; i < planeCount; i++) { Plane frust = planes[i]; for (j = 0; j < 8; j++) { distances[j] = frust.Distance(transformed[j]); if (distances[j] < 0) { break; } } if (j == 8) { // all points were behind one of the planes // TODO: tr.pc.c_box_cull_out++; return(true); } } // TODO: tr.pc.c_box_cull_in++; return(false); // not culled }
/// <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 FromTransformedBounds(idBounds bounds, Vector3 origin, Matrix axis) { Vector3 center = (bounds.Min + bounds.Max) * 0.5f; Vector3 extents = bounds.Max - center; Vector3 rotatedExtents = Vector3.Zero; rotatedExtents.X = idMath.Abs(extents.X * axis.M11) + idMath.Abs(extents.Y * axis.M21) + idMath.Abs(extents.Y * axis.M31); rotatedExtents.Y = idMath.Abs(extents.X * axis.M12) + idMath.Abs(extents.Y * axis.M22) + idMath.Abs(extents.Y * axis.M32); rotatedExtents.Z = idMath.Abs(extents.X * axis.M13) + idMath.Abs(extents.Y * axis.M23) + idMath.Abs(extents.Y * axis.M33); center = origin + Vector3.Transform(center, axis); idBounds result = new idBounds(); result.Min = center - rotatedExtents; result.Max = center + rotatedExtents; return(result); }
public bool AddBounds(idBounds b) { bool expanded = false; if (b.Min.X < this.Min.X) { this.Min.X = b.Min.X; expanded = true; } if (b.Min.Y < this.Min.Y) { this.Min.Y = b.Min.Y; expanded = true; } if (b.Min.Z < this.Min.Z) { this.Min.Z = b.Min.Z; expanded = true; } if (b.Max.X > this.Max.X) { this.Max.X = b.Max.X; expanded = true; } if (b.Max.Y > this.Max.Y) { this.Max.Y = b.Max.Y; expanded = true; } if (b.Max.Z > this.Max.Z) { this.Max.Z = b.Max.Z; expanded = true; } return(expanded); }
/// <summary> /// Most tight bounds for the translational movement of the given bounds. /// </summary> /// <param name="origin"></param> /// <param name="axis"></param> /// <param name="translation"></param> /// <returns></returns> public static idBounds FromBoundsTranslation(idBounds bounds, Vector3 origin, Matrix axis, Vector3 translation) { idBounds result; if (axis != Matrix.Identity) { result = FromTransformedBounds(bounds, origin, axis); } else { result = new idBounds(bounds.Min + origin, bounds.Max + origin); } if (translation.X < 0.0f) { bounds.Min.X += translation.X; } else { bounds.Max.X += translation.X; } if (translation.Y < 0.0f) { bounds.Min.Y += translation.Y; } else { bounds.Max.Y += translation.Y; } if (translation.Z < 0.0f) { bounds.Min.Z += translation.Z; } else { bounds.Max.Z += translation.Z; } return(bounds); }
/// <summary> /// Most tight bounds for the translational movement of the given point. /// </summary> /// <param name="point"></param> /// <param name="translation"></param> /// <returns></returns> public static idBounds FromPointTranslation(Vector3 point, Vector3 translation) { idBounds result = new idBounds(); if (translation.X < 0.0f) { result.Min.X = point.X + translation.X; result.Max.X = point.X; } else { result.Min.X = point.X; result.Max.X = point.X + translation.X; } if (translation.Y < 0.0f) { result.Min.Y = point.Y + translation.Y; result.Max.Y = point.Y; } else { result.Min.Y = point.Y; result.Max.Y = point.Y + translation.Y; } if (translation.Z < 0.0f) { result.Min.Z = point.Z + translation.Z; result.Max.Z = point.Z; } else { result.Min.Z = point.Z; result.Max.Z = point.Z + translation.Z; } return(result); }
/// <summary> /// Most tight bounds for the translational movement of the given bounds. /// </summary> /// <param name="origin"></param> /// <param name="axis"></param> /// <param name="translation"></param> /// <returns></returns> public static idBounds FromBoundsTranslation(idBounds bounds, Vector3 origin, Matrix axis, Vector3 translation) { idBounds result; if(axis != Matrix.Identity) { result = FromTransformedBounds(bounds, origin, axis); } else { result = new idBounds(bounds.Min + origin, bounds.Max + origin); } if(translation.X < 0.0f) { bounds.Min.X += translation.X; } else { bounds.Max.X += translation.X; } if(translation.Y < 0.0f) { bounds.Min.Y += translation.Y; } else { bounds.Max.Y += translation.Y; } if(translation.Z < 0.0f) { bounds.Min.Z += translation.Z; } else { bounds.Max.Z += translation.Z; } return bounds; }
public static idBounds operator +(idBounds a, idBounds b) { idBounds newBounds = new idBounds(); newBounds.AddBounds(a); newBounds.AddBounds(b); return newBounds; }
public static idBounds Expand(idBounds bounds, float d) { return new idBounds(new Vector3(bounds.Min.X - d, bounds.Min.Y - d, bounds.Min.Z - d), new Vector3(bounds.Max.X + d, bounds.Max.Y + d, bounds.Max.Z + d)); }
public idTraceModel(idBounds bounds, int sideCount) { SetupCylinder(bounds, sideCount); }
public ContentFlags Contents(Vector3 start, idClipModel model, Matrix traceModelAxis, ContentFlags contentMask, idEntity passEntity) { idConsole.Warning("TODO: idClip.Contents"); ContentFlags contents = ContentFlags.None; idBounds traceModelBounds = new idBounds(); // TODO /*idTraceModel traceModel = TraceModelForClipModel(model); if((passEntity == null) || (passEntity.Index != idR.EntityIndexWorld)) { // test world _contentCount++; // TODO: NEED ENGINE SOURCE contents = idR.CollisionModelManager.Contents(start, traceModel, traceModelAxis, contentMask, 0, Vector3.Zero, Matrix.Identity); } else { contents = ContentFlags.None; } if(traceModel == null) { traceModelBounds.Min = start; traceModelBounds.Max = start; } else if(traceModelAxis != Matrix.Identity) { traceModelBounds = idBounds.FromTransformedBounds(traceModel.Bounds, start, traceModelAxis); } else { traceModelBounds.Min = traceModel.Bounds.Min + start; traceModelBounds.Max = traceModel.Bounds.Max + start; } idClipModel[] traceModelList = GetTraceClipModels(traceModelBounds, -1, passEntity); foreach(idClipModel touch in traceModelList) { if(touch == null) { continue; } // no contents test with render models if(touch.RenderModelHandle != -1) { continue; } // if the entity does not have any contents we are looking for if((touch.Contents & contentMask) == ContentFlags.None) { continue; } // if the entity has no new contents flags if((touch.Contents & contents) == touch.Contents) { continue; } _contentCount++; // TODO /*if(idR.CollisionModelManager.Contents(start, traceModel, traceModelAxis, contentMask, touch.Handle, touch.Origin, touch.Axis) > 0) { contents |= (touch.Contents & contentMask); }*/ /*}*/ return contents; }
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 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 bool AddBounds(idBounds b) { bool expanded = false; if(b.Min.X < this.Min.X) { this.Min.X = b.Min.X; expanded = true; } if(b.Min.Y < this.Min.Y) { this.Min.Y = b.Min.Y; expanded = true; } if(b.Min.Z < this.Min.Z) { this.Min.Z = b.Min.Z; expanded = true; } if(b.Max.X > this.Max.X) { this.Max.X = b.Max.X; expanded = true; } if(b.Max.Y > this.Max.Y) { this.Max.Y = b.Max.Y; expanded = true; } if(b.Max.Z > this.Max.Z) { this.Max.Z = b.Max.Z; expanded = true; } return expanded; }
/// <summary> /// Axial bounding box. /// </summary> /// <param name="bounds"></param> public idTraceModel(idBounds bounds) { InitBox(); SetupBox(bounds); }
public idTraceModel() { _type = TraceModelType.Invalid; _bounds = idBounds.Zero; _edges = new TraceModelEdge[0]; _polygons = new TraceModelPolygon[0]; _vertices = new Vector3[0]; }
public void SetupCylinder(idBounds bounds, int sideCount) { int n = sideCount; if(n < 3) { n = 3; } if((n * 2) > MaxVertices) { idConsole.WriteLine("WARNING: idTraceModel::SetupCylinder: too many vertices"); n = MaxVertices / 2; } if((n * 3) > MaxEdges) { idConsole.WriteLine("WARNING: idTraceModel::SetupCylinder: too many sides"); n = MaxEdges / 3; } if((n + 2) > MaxPolygons) { idConsole.WriteLine("WARNING: idTraceModel::SetupCylinder: too many polygons"); n = MaxPolygons - 2; } _type = TraceModelType.Cylinder; _vertices = new Vector3[n * 2]; _edges = new TraceModelEdge[n * 3]; _polygons = new TraceModelPolygon[n + 2]; _offset = (bounds.Min + bounds.Max) * 0.5f; Vector3 halfSize = bounds.Max - _offset; for(int i = 0; i < n; i++) { // verts float angle = idMath.TwoPi * i / n; _vertices[i].X = idMath.Cos(angle) * halfSize.X + _offset.X; _vertices[i].Y = idMath.Sin(angle) * halfSize.Y + _offset.Y; _vertices[i].Z = -halfSize.Z + _offset.Z; _vertices[n + i].X = _vertices[i].X; _vertices[n + i].Y = _vertices[i].Y; _vertices[n + i].Z = halfSize.Z + _offset.Z; // edges int ii = i + 1; int n2 = n << 1; _edges[ii].V[0] = i; _edges[ii].V[1] = ii % n; _edges[n + ii].V[0] = _edges[ii].V[0] + n; _edges[n + ii].V[1] = _edges[ii].V[1] + n; _edges[n2 + ii].V[0] = i; _edges[n2 + ii].V[1] = n + i; // vertical polygon edges _polygons[i].Edges = new int[4]; _polygons[i].Edges[0] = ii; _polygons[i].Edges[1] = n2 + (ii % n) + 1; _polygons[i].Edges[2] = -(n + ii); _polygons[i].Edges[3] = -(n2 + ii); // bottom and top polygon edges _polygons[n].Edges[i] = -(n - i); _polygons[n + 1].Edges[i] = n + ii; } // bottom and top polygon numEdges _polygons[n].Edges = new int[n]; _polygons[n + 1].Edges = new int[n]; // polygons for(int i = 0; i < n; i++) { // vertical polygon plane _polygons[i].Normal = Vector3.Cross(_vertices[(i + 1) % n] - _vertices[i], _vertices[n + i] - _vertices[i]); _polygons[i].Normal.Normalize(); // vertical polygon bounds _polygons[i].Bounds.Clear(); _polygons[i].Bounds.AddPoint(_vertices[i]); _polygons[i].Bounds.AddPoint(_vertices[(i + 1) % n]); _polygons[i].Bounds.Min.Z = -halfSize.Z + _offset.Z; _polygons[i].Bounds.Max.Z = halfSize.Z + _offset.Z; } // bottom and top polygon plane _polygons[n].Normal = new Vector3(0, 0, -1.0f); _polygons[n].Distance = -bounds.Min.Z; _polygons[n + 1].Normal = new Vector3(0, 0, 1.0f); _polygons[n + 1].Distance = bounds.Max.Z; // trm bounds _bounds = bounds; // bottom and top polygon bounds _polygons[n].Bounds = bounds; _polygons[n].Bounds.Max.Z = bounds.Min.Z; _polygons[n + 1].Bounds = bounds; _polygons[n + 1].Bounds.Min.Z = bounds.Max.Z; // convex model _isConvex = true; GenerateEdgeNormals(); }
public void SetupBox(idBounds bounds) { if(_type != TraceModelType.Box) { InitBox(); } // offset to center _offset = (bounds.Min + bounds.Max) * 0.5f; // set box vertices _vertices = new Vector3[8]; for(int i = 0; i < 8; i++) { _vertices[i] = new Vector3( ((i ^ (i >> 1)) == 0) ? bounds.Min.X : bounds.Max.X, (((i >> 1) & 1) == 0) ? bounds.Min.Y : bounds.Max.Y, (((i >> 2) & 1) == 0) ? bounds.Min.Z : bounds.Max.Z ); } // set polygon plane distances _polygons = new TraceModelPolygon[6]; _polygons[0].Distance = -_bounds.Min.Z; _polygons[1].Distance = bounds.Max.Z; _polygons[2].Distance = -bounds.Min.Y; _polygons[3].Distance = bounds.Max.X; _polygons[4].Distance = bounds.Max.Y; _polygons[5].Distance = -bounds.Min.X; // set polygon bounds for(int i = 0; i < 6; i++) { _polygons[i].Bounds = bounds; _polygons[i].Edges = new int[0]; } _polygons[0].Bounds.Max.Z = bounds.Min.Z; _polygons[1].Bounds.Min.Z = bounds.Max.Z; _polygons[2].Bounds.Max.Y = bounds.Min.Y; _polygons[3].Bounds.Min.X = bounds.Max.X; _polygons[4].Bounds.Min.Y = bounds.Max.Y; _polygons[5].Bounds.Max.X = bounds.Min.X; _bounds = bounds; }
/// <summary> /// Builds a uniformly subdivided tree for the given world size. /// </summary> /// <param name="depth"></param> /// <param name="bounds"></param> /// <param name="?"></param> /// <returns></returns> private ClipSector CreateClipSectors(int depth, idBounds bounds, ref Vector3 maxSector) { idBounds front, back; ClipSector anode = _clipSectors[_clipSectorCount] = new ClipSector(); _clipSectorCount++; if(depth == idClip.MaxSectorDepth) { anode.Axis = -1; anode.Children[0] = anode.Children[1] = null; if((bounds.Max.X - bounds.Min.X) > maxSector.X) { maxSector.X = bounds.Max.X - bounds.Min.X; } if((bounds.Max.Y - bounds.Min.Y) > maxSector.Y) { maxSector.Y = bounds.Max.Y - bounds.Min.Y; } if((bounds.Max.Z - bounds.Min.Z) > maxSector.Z) { maxSector.Z = bounds.Max.Z - bounds.Min.Z; } return anode; } Vector3 size = bounds.Max - bounds.Min; front = bounds; back = bounds; if((size.X >= size.Y) && (size.X >= size.Z)) { anode.Axis = 0; anode.Distance = 0.5f * (bounds.Max.X + bounds.Min.X); front.Min.X = back.Max.X = anode.Distance; } else if((size.Y >= size.X) && (size.Y >= size.Z)) { anode.Axis = 1; anode.Distance = 0.5f * (bounds.Max.Y + bounds.Min.Y); front.Min.Y = back.Max.Y = anode.Distance; } else { anode.Axis = 2; anode.Distance = 0.5f * (bounds.Max.Z + bounds.Min.Z); front.Min.Z = back.Max.Z = anode.Distance; } anode.Children[0] = CreateClipSectors(depth + 1, front, ref maxSector); anode.Children[1] = CreateClipSectors(depth + 1, back, ref maxSector); return anode; }
/// <summary> /// /// </summary> /// <remarks> /// an ent will be excluded from testing if: /// cm->entity == passEntity (don't clip against the pass entity) /// cm->entity == passOwner (missiles don't clip with owner) /// cm->owner == passEntity (don't interact with your own missiles) /// cm->owner == passOwner (don't interact with other missiles from same owner) /// </remarks> /// <param name="bounds"></param> /// <param name="contentMask"></param> /// <param name="passEntity"></param> /// <returns></returns> private idClipModel[] GetTraceClipModels(idBounds bounds, ContentFlags contentMask, idEntity passEntity) { idConsole.Warning("TODO: idClip.GetTraceClipModels"); // TODO /*int i, num; idClipModel *cm; idEntity *passOwner; num = ClipModelsTouchingBounds( bounds, contentMask, clipModelList, MAX_GENTITIES ); if ( !passEntity ) { return num; } if ( passEntity->GetPhysics()->GetNumClipModels() > 0 ) { passOwner = passEntity->GetPhysics()->GetClipModel()->GetOwner(); } else { passOwner = NULL; } for ( i = 0; i < num; i++ ) { cm = clipModelList[i]; // check if we should ignore this entity if ( cm->entity == passEntity ) { clipModelList[i] = NULL; // don't clip against the pass entity } else if ( cm->entity == passOwner ) { clipModelList[i] = NULL; // missiles don't clip with their owner } else if ( cm->owner ) { if ( cm->owner == passEntity ) { clipModelList[i] = NULL; // don't clip against own missiles } else if ( cm->owner == passOwner ) { clipModelList[i] = NULL; // don't clip against other missiles from same owner } } } return num;*/ return null; }
/// <summary> /// Most tight bounds for the translational movement of the given point. /// </summary> /// <param name="point"></param> /// <param name="translation"></param> /// <returns></returns> public static idBounds FromPointTranslation(Vector3 point, Vector3 translation) { idBounds result = new idBounds(); if(translation.X < 0.0f) { result.Min.X = point.X + translation.X; result.Max.X = point.X; } else { result.Min.X = point.X; result.Max.X = point.X + translation.X; } if(translation.Y < 0.0f) { result.Min.Y = point.Y + translation.Y; result.Max.Y = point.Y; } else { result.Min.Y = point.Y; result.Max.Y = point.Y + translation.Y; } if(translation.Z < 0.0f) { result.Min.Z = point.Z + translation.Z; result.Max.Z = point.Z; } else { result.Min.Z = point.Z; result.Max.Z = point.Z + translation.Z; } return result; }
public static idBounds FromTransformedBounds(idBounds bounds, Vector3 origin, Matrix axis) { Vector3 center = (bounds.Min + bounds.Max) * 0.5f; Vector3 extents = bounds.Max - center; Vector3 rotatedExtents = Vector3.Zero; rotatedExtents.X = idMath.Abs(extents.X * axis.M11) + idMath.Abs(extents.Y * axis.M21) + idMath.Abs(extents.Y * axis.M31); rotatedExtents.Y = idMath.Abs(extents.X * axis.M12) + idMath.Abs(extents.Y * axis.M22) + idMath.Abs(extents.Y * axis.M32); rotatedExtents.Z = idMath.Abs(extents.X * axis.M13) + idMath.Abs(extents.Y * axis.M23) + idMath.Abs(extents.Y * axis.M33); center = origin + Vector3.Transform(center, axis); idBounds result = new idBounds(); result.Min = center - rotatedExtents; result.Max = center + rotatedExtents; return result; }
public static idBounds Expand(idBounds bounds, float d) { return(new idBounds(new Vector3(bounds.Min.X - d, bounds.Min.Y - d, bounds.Min.Z - d), new Vector3(bounds.Max.X + d, bounds.Max.Y + d, bounds.Max.Z + d))); }
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 void Init() { Vector3 maxSector = Vector3.Zero; // clear clip sectors _clipSectors = new ClipSector[MaxSectors]; _clipSectorCount = 0; _touchCount = -1; // get world map bounds CollisionModel collisionModel = idR.CollisionModelManager.LoadModel("worldMap", false); if(collisionModel != null) { _worldBounds = collisionModel.Bounds; } // create world sectors CreateClipSectors(0, _worldBounds, ref maxSector); Vector3 size = _worldBounds.Max - _worldBounds.Min; idConsole.WriteLine("map bounds are ({0})", size); idConsole.WriteLine("max clip sector is ({0})", maxSector); // initialize a default clip model _defaultClipModel = new idClipModel(); _defaultClipModel.LoadModel(new idTraceModel(idBounds.Expand(8))); // set counters to zero _rotationCount = 0; _translationCount = 0; _motionCount = 0; _renderModelTraceCount = 0; _contentCount = 0; _contactCount = 0; }