// Once all of the triangle pairs that need intersection testing have been determined, we can do the actual intersection testing // Get out the scissors !!! protected virtual void Snip(ModelInput in_a, ModelInput in_b, List<TrianglePair> pairs) { List<int> first_tris = new List<int>(); List<int> second_tris = new List<int>(); foreach (TrianglePair pair in pairs) { if (!first_tris.Contains(pair.a)) first_tris.Add(pair.a); if (!second_tris.Contains(pair.b)) second_tris.Add(pair.b); } WorkingModel a = in_a.ToWorkingModel(0, first_tris); WorkingModel b = in_b.ToWorkingModel(1, second_tris); WorkingModel.Intersect(a, b, pairs); List<BasicModelVert> first_notsafe_bmv = a.GetBMVList(first_in, first_xform); List<BasicModelVert> first_safe_bmv = new List<BasicModelVert>(); for (int i = 0; i < first_in.a_vert.Length; i++) if (!first_tris.Contains(i)) for (int j = 0; j < 3; j++) { int xyz = (int)((j == 0 ? first_in.a_vert : j == 1 ? first_in.b_vert : first_in.c_vert)[i]); int uv = (int)((j == 0 ? first_in.a_uv : j == 1 ? first_in.b_uv : first_in.c_uv)[i]); int norm = (int)((j == 0 ? first_in.a_norm : j == 1 ? first_in.b_norm : first_in.c_norm)[i]); first_safe_bmv.Add(new BasicModelVert { position = first_xform.TransformVec3(new Vec3 { x = first_in.x[xyz], y = first_in.y[xyz], z = first_in.z[xyz] }, 1.0), uv = new Vec2 { x = first_in.u[uv], y = first_in.v[uv] }, normal = Vec3.Normalize(first_xform.TransformVec3(new Vec3 { x = first_in.nx[norm], y = first_in.ny[norm], z = first_in.nz[norm] }, 0.0)) }); } List<BasicModelVert> second_notsafe_bmv = b.GetBMVList(second_in, second_xform); List<BasicModelVert> second_safe_bmv = new List<BasicModelVert>(); for (int i = 0; i < second_in.a_vert.Length; i++) if (!second_tris.Contains(i)) for (int j = 0; j < 3; j++) { int xyz = (int)((j == 0 ? second_in.a_vert : j == 1 ? second_in.b_vert : second_in.c_vert)[i]); int uv = (int)((j == 0 ? second_in.a_uv : j == 1 ? second_in.b_uv : second_in.c_uv)[i]); int norm = (int)((j == 0 ? second_in.a_norm : j == 1 ? second_in.b_norm : second_in.c_norm)[i]); second_safe_bmv.Add(new BasicModelVert { position = second_xform.TransformVec3(new Vec3 { x = second_in.x[xyz], y = second_in.y[xyz], z = second_in.z[xyz] }, 1.0), uv = new Vec2 { x = second_in.u[uv], y = second_in.v[uv] }, normal = Vec3.Normalize(second_xform.TransformVec3(new Vec3 { x = second_in.nx[norm], y = second_in.ny[norm], z = second_in.nz[norm] }, 0.0)) }); } cutEdges = new List<Vec3[]>(); cutEdges.AddRange(a.GetCutEdgesList()); cutEdges.AddRange(b.GetCutEdgesList()); cutPoints = new List<Vec3>(); foreach (Vec3[] edge in b.GetCutEdgesList()) foreach (Vec3 vert in edge) if (!cutPoints.Exists((v) => (v - vert).ComputeMagnitudeSquared() < 0.0000000000000000000001)) cutPoints.Add(vert); List<BasicModelVert> first_bmv_trimmed = ScrapTrimmedStuff(first_safe_bmv, first_notsafe_bmv, cutEdges, first_keep); List<BasicModelVert> second_bmv_trimmed = ScrapTrimmedStuff(second_safe_bmv, second_notsafe_bmv, cutEdges, second_keep); first_out = BMVListToModel(first_bmv_trimmed); second_out = BMVListToModel(second_bmv_trimmed); }
public static void IntersectTest(int a_tri, ModelInput a_obj, int b_tri, ModelInput b_obj, out Vec2[,] intersections, out Vec3[] a_verts, out Vec3[] b_verts) { a_verts = new Vec3[] { a_obj.verts[a_obj.t_v[a_tri, 0]], a_obj.verts[a_obj.t_v[a_tri, 1]], a_obj.verts[a_obj.t_v[a_tri, 2]] }; b_verts = new Vec3[] { b_obj.verts[b_obj.t_v[b_tri, 0]], b_obj.verts[b_obj.t_v[b_tri, 1]], b_obj.verts[b_obj.t_v[b_tri, 2]] }; intersections = Util.TriangleTriangleIntersection(a_verts, b_verts); }
// Do the CSG stuff // This is a virtual function, just in case someone thinks they can do it better public virtual void Compute() { first_blob = ModelInput.FromBasicModelData(first_in, first_xform); second_blob = ModelInput.FromBasicModelData(second_in, second_xform); /* CSGModel derp1 = ModelUtil.ModelFromBMD(first_in, first_xform); CSGModel derp2 = ModelUtil.ModelFromBMD(second_in, second_xform); int count = 0; ModelIntersectTree.CullIntersections(derp1, derp2, (i, j) => { count++; }); */ AABB aa_box = first_blob.AABB; AABB bb_box = second_blob.AABB; if (AABB.CheckIntersection(aa_box, bb_box)) // check whether their bounding boxes even intersect... if they don't, most of the math can be skipped! { AABB intersection = AABB.Intersection(aa_box, bb_box); PartitioningGrid grid = new PartitioningGrid(intersection, 5); first_blob.PopulateGrid(grid, 0); second_blob.PopulateGrid(grid, 1); List<TrianglePair> pairs = new List<TrianglePair>(); grid.ForLeafLevelPairs( (first, second) => { pairs.Add(new TrianglePair { a = first, b = second }); }); Snip(first_blob, second_blob, pairs); } else Snip(first_blob, second_blob, new List<TrianglePair>()); }