/// <summary> /// Exact compare, no epsilon. /// </summary> /// <param name="sphere"></param> /// <returns></returns> public bool Equals(idSphere sphere) { return((_origin == sphere.Origin) && (_radius == sphere.Radius)); }
/// <summary> /// Compare with epsilon. /// </summary> /// <param name="sphere"></param> /// <param name="epsilon"></param> /// <returns></returns> public bool Equals(idSphere sphere, float epsilon) { return((_origin.Compare(sphere.Origin, epsilon) == true) && (idMath.Abs(_radius - sphere.Radius) <= epsilon)); }
/// <summary> /// Exact compare, no epsilon. /// </summary> /// <param name="sphere"></param> /// <returns></returns> public bool Equals(idSphere sphere) { return ((_origin == sphere.Origin) && (_radius == sphere.Radius)); }
/// <summary> /// Compare with epsilon. /// </summary> /// <param name="sphere"></param> /// <param name="epsilon"></param> /// <returns></returns> public bool Equals(idSphere sphere, float epsilon) { return ((_origin.Compare(sphere.Origin, epsilon) == true) && (idMath.Abs(_radius - sphere.Radius) <= epsilon)); }
/// <remarks> /// Used for both light volumes and model volumes. /// <para/> /// This does not clip the points by the planes, so some slop occurs. /// <para/> /// tr.viewCount should be bumped before calling, allowing it /// to prevent double checking areas. /// <para/> /// We might alternatively choose to do this with an area flow. /// </remarks> /// <param name="def"></param> /// <param name="?"></param> /// <param name="sphere"></param> /// <param name="pointCount"></param> /// <param name="points"></param> private void PushVolumeIntoTree_r(idRenderEntity def, /* idRenderLight */ object light, idSphere sphere, int pointCount, Vector3[] points, int nodeNumber) { if(nodeNumber < 0) { int areaNumber = -1 - nodeNumber; PortalArea area = _portalAreas[areaNumber]; if(area.ViewCount == idE.RenderSystem.ViewCount) { return; // already added a reference here } area.ViewCount = idE.RenderSystem.ViewCount; if(def != null) { AddEntityRefToArea(def, area); } if(light != null) { idConsole.Warning("TODO: AddLightRefToArea( light, area );"); } return; } AreaNode node = _areaNodes[nodeNumber]; // if we know that all possible children nodes only touch an area // we have already marked, we can early out if((idE.CvarSystem.GetBool("r_useNodeCommonChildren") == true) && (node.CommonChildrenArea != idRenderWorld.ChildrenHaveMultipleAreas)) { // note that we do NOT try to set a reference in this area // yet, because the test volume may yet wind up being in the // solid part, which would cause bounds slightly poked into // a wall to show up in the next room if(_portalAreas[node.CommonChildrenArea].ViewCount == idE.RenderSystem.ViewCount) { return; } } // if the bounding sphere is completely on one side, don't // bother checking the individual points float distance = node.Plane.Distance(sphere.Origin); if(distance >= sphere.Radius) { nodeNumber = node.Children[0]; if(nodeNumber != 0) // 0 = solid { PushVolumeIntoTree_r(def, light, sphere, pointCount, points, nodeNumber); } return; } if(distance <= -sphere.Radius) { nodeNumber = node.Children[1]; if(nodeNumber != 0) // 0 = solid { PushVolumeIntoTree_r(def, light, sphere, pointCount, points, nodeNumber); } return; } // exact check all the points against the node plane bool front = false; bool back = false; for(int i = 0; i < pointCount; i++) { float d = ((points[i] * node.Plane.Normal) + new Vector3(node.Plane.Normal.Z, node.Plane.Normal.Z, node.Plane.Normal.Z)).Length(); if(d >= 0.0f) { front = true; } else if(d <= 0.0f) { back = true; } if((back == true) && (front == true)) { break; } } if(front == true) { nodeNumber = node.Children[0]; if(nodeNumber != 0) // 0 = solid { PushVolumeIntoTree_r(def, light, sphere, pointCount, points, nodeNumber); } } if(back == true) { nodeNumber = node.Children[1]; if(nodeNumber != 0) // 0 = solid { PushVolumeIntoTree_r(def, light, sphere, pointCount, points, nodeNumber); } } }
private void PushVolumeIntoTree(idRenderEntity def, /* idRenderLight */ object light, int pointCount, Vector3[] points) { if(_areaNodes == null) { return; } // calculate a bounding sphere for the points Vector3 mid = Vector3.Zero; Vector3 dir; float radSquared = 0; float lr = 0; for(int i = 0; i < pointCount; i++) { mid += points[i]; } mid *= (1.0f / pointCount); for(int i = 0; i < pointCount; i++) { dir = points[i] - mid; lr = (dir * dir).Length(); if(lr > radSquared) { radSquared = lr; } } idSphere sphere = new idSphere(mid, idMath.Sqrt(radSquared)); PushVolumeIntoTree_r(def, light, sphere, pointCount, points, 0); }