Gettin cross-section with raycast... Bounds problem?

Here is some code to get the cross-section of an object. I am using it to model boat and airplane physics (to get the surface area facing the flow at diff angles).

This code runs in the setup phase of the object. You can pass any GameObject to the script and it will return an lookup table containing the cross-section data. It’s pretty cool… small problem, it doesn’t work when the object’s center is not the center of the bounds of the object…

For example, if you take a sphere, and set it’s parent as some GameObject and then pass this GameObject to the method it works fine…ONLY if the sphere’s localPosition at 0,0,0. When the Sphere is off-center a bit, all of the raycasts miss it.

Now, if you look at the code, this should be absolutely impossible! The rays are fired relative to Bounds of the GameObject in world space… I can’t see anything in the code that would cause this to happen. It’s been driving me nuts all day.

Here is the code. If you get it to work please tell me how! Feel free to then use the code for whatever you want.

static public Vector4[, ,][] calculateCrossSections(GameObject g, float resolution, int rotationStep)
	{

		Quaternion q = g.transform.rotation;
		Vector3 p = g.transform.position;

		Bounds worldBounds = new Bounds();
		Renderer[] rs = g.GetComponentsInChildren<Renderer>();
		bool firstBound = true;
		
		Vector4[, ,][] csArea = new Vector4[360 / rotationStep, 360 / rotationStep, 360 / rotationStep][];
		
		for (int x = 0; x < 360; x += rotationStep)
			for (int y = 0; y < 360; y += rotationStep)
				for (int z = 0; z < 360; z += rotationStep)
				{
					g.transform.position = p;
					g.transform.rotation = q;
					g.transform.eulerAngles = new Vector3(x, y, z);
					//Bounds oldBounds = worldBounds;
					worldBounds = new Bounds();

					firstBound = true;
					
					foreach (Renderer r in rs)
					{
						//layerMask = layerMask | (1 << r.gameObject.layer);
						if (firstBound)
						{
							worldBounds = r.bounds;
							firstBound = false;
						}
						else
							worldBounds.Encapsulate(r.bounds);

					}


				
					
					int pxSize = Mathf.CeilToInt((worldBounds.size.x+2) / resolution);
					int pySize = Mathf.CeilToInt((worldBounds.size.y+2)/ resolution);

					List<Vector4> pixels = new List<Vector4>();
					Debug.Log(worldBounds);
					Debug.Log(worldBounds.size);
					Debug.Log(worldBounds.min);
					Debug.Log(worldBounds.max);

					for (int px = 0; px < pxSize; px++)
					{
						for (int py = 0; py < pySize; py++)
						{
							RaycastHit hit = new RaycastHit();
							Ray ray = new Ray(worldBounds.min +(Vector3.left + Vector3.back) + new Vector3(px * resolution, py * resolution, 0), Vector3.forward);
							hit = new RaycastHit();
							if (Physics.Raycast(ray, out hit, worldBounds.size.z+2))
							{
								Vector4 pixel = (Vector4)g.transform.InverseTransformPoint(hit.point);
								pixel.w = 1 - Vector3.Angle(ray.direction, hit.normal)/90f;
								pixels.Add(pixel);

							}
						}
					}
					Debug.Log("pcount" + pixels.Count);
					csArea[x / rotationStep, y / rotationStep, z / rotationStep] = pixels.ToArray<Vector4>();//pixels.OrderBy(v => v.w).ToArray<Vector4>();
				}
		g.transform.rotation = q;
		g.transform.position = p;
		return csArea;
	}

Oh if you are going to test this on an object make sure you set the rotationStep to some factor of 360, and nothing too low or you will be waiting a while. Try something like 90 for the rotationStep and set the resolution relative to the size of the object you are scanning.

ok I just thought of a quite possible reason this is happening… Could it be that the physX engine doesn’t update the position of colliders until the fixedUpdate? it’s quite possible. Now I will investigate that possibility.

Ok that was quick. I was right the physics engine doesn’t update the location of the collider until the next fixedUpdate. Got it working by putting this method in a coroutine and

yield return new WaitForFixedUpdate();

right after the rotation.

Since coroutines can’t have return methods I just pass the array as an “out” parameter and all is well.