public static IEnumerable <Triangle3D> BoxTriangles(Vector3 a, Vector3 b) { float x = a.X; float z = a.Y; float y = a.Z; float sx = b.X - a.X; float sz = b.Y - a.Y; float sy = b.Z - a.Z; List <short> myelements = new List <short>(); List <Vector3> myvertices = new List <Vector3>(); //top //if (drawtop) { short lastelement = (short)myvertices.Count; myvertices.Add(new Vector3(x + 0.0f * sx, z + 1.0f * sz, y + 0.0f * sy)); myvertices.Add(new Vector3(x + 0.0f * sx, z + 1.0f * sz, y + 1.0f * sy)); myvertices.Add(new Vector3(x + 1.0f * sx, z + 1.0f * sz, y + 0.0f * sy)); myvertices.Add(new Vector3(x + 1.0f * sx, z + 1.0f * sz, y + 1.0f * sy)); myelements.Add((short)(lastelement + 0)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); myelements.Add((short)(lastelement + 3)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); } //bottom - same as top, but z is 1 less. //if (drawbottom) { short lastelement = (short)myvertices.Count; myvertices.Add(new Vector3(x + 0.0f * sx, z + 0 * sz, y + 0.0f * sy)); myvertices.Add(new Vector3(x + 0.0f * sx, z + 0 * sz, y + 1.0f * sy)); myvertices.Add(new Vector3(x + 1.0f * sx, z + 0 * sz, y + 0.0f * sy)); myvertices.Add(new Vector3(x + 1.0f * sx, z + 0 * sz, y + 1.0f * sy)); myelements.Add((short)(lastelement + 0)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); myelements.Add((short)(lastelement + 3)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); } //front //if (drawfront) { short lastelement = (short)myvertices.Count; myvertices.Add(new Vector3(x + 0 * sx, z + 0 * sz, y + 0 * sy)); myvertices.Add(new Vector3(x + 0 * sx, z + 0 * sz, y + 1 * sy)); myvertices.Add(new Vector3(x + 0 * sx, z + 1 * sz, y + 0 * sy)); myvertices.Add(new Vector3(x + 0 * sx, z + 1 * sz, y + 1 * sy)); myelements.Add((short)(lastelement + 0)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); myelements.Add((short)(lastelement + 3)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); } //back - same as front, but x is 1 greater. //if (drawback) { short lastelement = (short)myvertices.Count; myvertices.Add(new Vector3(x + 1 * sx, z + 0 * sz, y + 0 * sy)); myvertices.Add(new Vector3(x + 1 * sx, z + 0 * sz, y + 1 * sy)); myvertices.Add(new Vector3(x + 1 * sx, z + 1 * sz, y + 0 * sy)); myvertices.Add(new Vector3(x + 1 * sx, z + 1 * sz, y + 1 * sy)); myelements.Add((short)(lastelement + 0)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); myelements.Add((short)(lastelement + 3)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); } //if (drawleft) { short lastelement = (short)myvertices.Count; myvertices.Add(new Vector3(x + 0 * sx, z + 0 * sz, y + 0 * sy)); myvertices.Add(new Vector3(x + 0 * sx, z + 1 * sz, y + 0 * sy)); myvertices.Add(new Vector3(x + 1 * sx, z + 0 * sz, y + 0 * sy)); myvertices.Add(new Vector3(x + 1 * sx, z + 1 * sz, y + 0 * sy)); myelements.Add((short)(lastelement + 0)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); myelements.Add((short)(lastelement + 3)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); } //right - same as left, but y is 1 greater. //if (drawright) { short lastelement = (short)myvertices.Count; myvertices.Add(new Vector3(x + 0 * sx, z + 0 * sz, y + 1 * sy)); myvertices.Add(new Vector3(x + 0 * sx, z + 1 * sz, y + 1 * sy)); myvertices.Add(new Vector3(x + 1 * sx, z + 0 * sz, y + 1 * sy)); myvertices.Add(new Vector3(x + 1 * sx, z + 1 * sz, y + 1 * sy)); myelements.Add((short)(lastelement + 0)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); myelements.Add((short)(lastelement + 3)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); } for (int i = 0; i < myelements.Count / 3; i++) { Triangle3D t = new Triangle3D(); t.PointA = myvertices[myelements[i * 3 + 0]]; t.PointB = myvertices[myelements[i * 3 + 1]]; t.PointC = myvertices[myelements[i * 3 + 2]]; yield return(t); } }
// intersect_RayTriangle(): intersect a ray with a 3D triangle // Input: a ray R, and a triangle T // Output: *I = intersection point (when it exists) // Return: -1 = triangle is degenerate (a segment or point) // 0 = disjoint (no intersect) // 1 = intersect in unique point I1 // 2 = are in the same plane public static int RayTriangle(Line3D R, Triangle3D T, out Vector3 I) { Vector3 u, v, n; // triangle vectors Vector3 dir, w0, w; // ray vectors float r, a, b; // params to calc ray-plane intersect I = new Vector3(); // get triangle edge vectors and plane normal u = T.PointB - T.PointA; v = T.PointC - T.PointA; //n = u.CrossProduct(v); // cross product Vector3.Cross(ref u, ref v, out n); //if (n == (Vector3D)0) // triangle is degenerate // return -1; // do not deal with this case dir = R.End - R.Start; // ray direction vector w0 = R.Start - T.PointA; a = -dot(n, w0); b = dot(n, dir); if (Math.Abs(b) < SMALL_NUM) { // ray is parallel to triangle plane if (a == 0) // ray lies in triangle plane return 2; else return 0; // ray disjoint from plane } // get intersect point of ray with triangle plane r = a / b; if (r < 0.0) // ray goes away from triangle return 0; // => no intersect // for a segment, also test if (r > 1.0) => no intersect I = R.Start + r * dir; // intersect point of ray and plane // is I inside T? float uu, uv, vv, wu, wv, D; uu = dot(u, u); uv = dot(u, v); vv = dot(v, v); w = I - T.PointA; wu = dot(w, u); wv = dot(w, v); D = uv * uv - uu * vv; // get and test parametric coords float s, t; s = (uv * wv - vv * wu) / D; if (s < 0.0 || s > 1.0) // I is outside T return 0; t = (uv * wu - uu * wv) / D; if (t < 0.0 || (s + t) > 1.0) // I is outside T return 0; return 1; // I is in T }
RayTriangle(Line3D R, Triangle3D T, out Vector3 I) { Vector3 u, v, n; // triangle vectors Vector3 dir, w0, w; // ray vectors float r, a, b; // params to calc ray-plane intersect I = new Vector3(); // get triangle edge vectors and plane normal u = T.PointB - T.PointA; v = T.PointC - T.PointA; //n = u.CrossProduct(v); // cross product Vector3.Cross(ref u, ref v, out n); //if (n == (Vector3D)0) // triangle is degenerate // return -1; // do not deal with this case dir = R.End - R.Start; // ray direction vector w0 = R.Start - T.PointA; a = -dot(n, w0); b = dot(n, dir); if (Math.Abs(b) < SMALL_NUM) { // ray is parallel to triangle plane if (a == 0) // ray lies in triangle plane { return(2); } else { return(0); // ray disjoint from plane } } // get intersect point of ray with triangle plane r = a / b; if (r < 0.0) // ray goes away from triangle { return(0); // => no intersect } // for a segment, also test if (r > 1.0) => no intersect I = R.Start + r * dir; // intersect point of ray and plane // is I inside T? float uu, uv, vv, wu, wv, D; uu = dot(u, u); uv = dot(u, v); vv = dot(v, v); w = I - T.PointA; wu = dot(w, u); wv = dot(w, v); D = uv * uv - uu * vv; // get and test parametric coords float s, t; s = (uv * wv - vv * wu) / D; if (s < 0.0 || s > 1.0) // I is outside T { return(0); } t = (uv * wu - uu * wv) / D; if (t < 0.0 || (s + t) > 1.0) // I is outside T { return(0); } return(1); // I is in T }
static float SMALL_NUM = 0.00000001f; // anything that avoids division overflow #endregion Fields #region Methods public static IEnumerable<Triangle3D> BoxTriangles(Vector3 a, Vector3 b) { float x = a.X; float z = a.Y; float y = a.Z; float sx = b.X - a.X; float sz = b.Y - a.Y; float sy = b.Z - a.Z; List<short> myelements = new List<short>(); List<Vector3> myvertices = new List<Vector3>(); //top //if (drawtop) { short lastelement = (short)myvertices.Count; myvertices.Add(new Vector3(x + 0.0f * sx, z + 1.0f * sz, y + 0.0f * sy)); myvertices.Add(new Vector3(x + 0.0f * sx, z + 1.0f * sz, y + 1.0f * sy)); myvertices.Add(new Vector3(x + 1.0f * sx, z + 1.0f * sz, y + 0.0f * sy)); myvertices.Add(new Vector3(x + 1.0f * sx, z + 1.0f * sz, y + 1.0f * sy)); myelements.Add((short)(lastelement + 0)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); myelements.Add((short)(lastelement + 3)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); } //bottom - same as top, but z is 1 less. //if (drawbottom) { short lastelement = (short)myvertices.Count; myvertices.Add(new Vector3(x + 0.0f * sx, z + 0 * sz, y + 0.0f * sy)); myvertices.Add(new Vector3(x + 0.0f * sx, z + 0 * sz, y + 1.0f * sy)); myvertices.Add(new Vector3(x + 1.0f * sx, z + 0 * sz, y + 0.0f * sy)); myvertices.Add(new Vector3(x + 1.0f * sx, z + 0 * sz, y + 1.0f * sy)); myelements.Add((short)(lastelement + 0)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); myelements.Add((short)(lastelement + 3)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); } //front //if (drawfront) { short lastelement = (short)myvertices.Count; myvertices.Add(new Vector3(x + 0 * sx, z + 0 * sz, y + 0 * sy)); myvertices.Add(new Vector3(x + 0 * sx, z + 0 * sz, y + 1 * sy)); myvertices.Add(new Vector3(x + 0 * sx, z + 1 * sz, y + 0 * sy)); myvertices.Add(new Vector3(x + 0 * sx, z + 1 * sz, y + 1 * sy)); myelements.Add((short)(lastelement + 0)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); myelements.Add((short)(lastelement + 3)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); } //back - same as front, but x is 1 greater. //if (drawback) { short lastelement = (short)myvertices.Count; myvertices.Add(new Vector3(x + 1 * sx, z + 0 * sz, y + 0 * sy)); myvertices.Add(new Vector3(x + 1 * sx, z + 0 * sz, y + 1 * sy)); myvertices.Add(new Vector3(x + 1 * sx, z + 1 * sz, y + 0 * sy)); myvertices.Add(new Vector3(x + 1 * sx, z + 1 * sz, y + 1 * sy)); myelements.Add((short)(lastelement + 0)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); myelements.Add((short)(lastelement + 3)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); } //if (drawleft) { short lastelement = (short)myvertices.Count; myvertices.Add(new Vector3(x + 0 * sx, z + 0 * sz, y + 0 * sy)); myvertices.Add(new Vector3(x + 0 * sx, z + 1 * sz, y + 0 * sy)); myvertices.Add(new Vector3(x + 1 * sx, z + 0 * sz, y + 0 * sy)); myvertices.Add(new Vector3(x + 1 * sx, z + 1 * sz, y + 0 * sy)); myelements.Add((short)(lastelement + 0)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); myelements.Add((short)(lastelement + 3)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); } //right - same as left, but y is 1 greater. //if (drawright) { short lastelement = (short)myvertices.Count; myvertices.Add(new Vector3(x + 0 * sx, z + 0 * sz, y + 1 * sy)); myvertices.Add(new Vector3(x + 0 * sx, z + 1 * sz, y + 1 * sy)); myvertices.Add(new Vector3(x + 1 * sx, z + 0 * sz, y + 1 * sy)); myvertices.Add(new Vector3(x + 1 * sx, z + 1 * sz, y + 1 * sy)); myelements.Add((short)(lastelement + 0)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); myelements.Add((short)(lastelement + 3)); myelements.Add((short)(lastelement + 1)); myelements.Add((short)(lastelement + 2)); } for (int i = 0; i < myelements.Count / 3; i++) { Triangle3D t = new Triangle3D(); t.PointA = myvertices[myelements[i * 3 + 0]]; t.PointB = myvertices[myelements[i * 3 + 1]]; t.PointC = myvertices[myelements[i * 3 + 2]]; yield return t; } }