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;
}