public List<BasicModelVert> GetBMVList(BasicModelData model, Mat4 xform) { List<BasicModelVert> list = new List<BasicModelVert>(); foreach (CutTriangle tri in cutTriangles) { List<WorkingVertex> triVerts = tri.GetCutTriangleVerts(); foreach(WorkingVertex vert in triVerts) list.Add(CSG.WorkingVertexToBMV(vert.position.xyz, vert.vinfo, model, xform, this)); } return list; }
public List <BasicModelVert> GetBMVList(BasicModelData model, Mat4 xform) { List <BasicModelVert> list = new List <BasicModelVert>(); foreach (CutTriangle tri in cutTriangles) { List <WorkingVertex> triVerts = tri.GetCutTriangleVerts(); foreach (WorkingVertex vert in triVerts) { list.Add(CSG.WorkingVertexToBMV(vert.position.xyz, vert.vinfo, model, xform, this)); } } return(list); }
public static CSGModel ModelFromBMD(BasicModelData input, Mat4 xform) { List<Vec3> verts = new List<Vec3>(); List<VInfo> vinfos = new List<VInfo>(); CopyAndTransformVert vx = VertexTransformationByMat4(xform); CopyAndTransformVInfo vi = BMDVInfoTransformationByMat4(xform); for (int i = 0; i < input.a_vert.Length; i++) { TransformAndAddVec3(verts, new Vec3 { x = input.x[input.a_vert[i]], y = input.y[input.a_vert[i]], z = input.z[input.a_vert[i]] }, vx); TransformAndAddVec3(verts, new Vec3 { x = input.x[input.b_vert[i]], y = input.y[input.b_vert[i]], z = input.z[input.b_vert[i]] }, vx); TransformAndAddVec3(verts, new Vec3 { x = input.x[input.c_vert[i]], y = input.y[input.c_vert[i]], z = input.z[input.c_vert[i]] }, vx); TransformAndAddVInfo(vinfos, new BMDVInfo { material = nextMaterial, uv = new Vec2 { x = input.u[input.a_uv[i]], y = input.v[input.a_uv[i]] }, normal = new Vec3 { x = input.nx[input.a_norm[i]], y = input.ny[input.a_norm[i]], z = input.nz[input.a_norm[i]] } }, vi); TransformAndAddVInfo(vinfos, new BMDVInfo { material = nextMaterial, uv = new Vec2 { x = input.u[input.b_uv[i]], y = input.v[input.b_uv[i]] }, normal = new Vec3 { x = input.nx[input.b_norm[i]], y = input.ny[input.b_norm[i]], z = input.nz[input.b_norm[i]] } }, vi); TransformAndAddVInfo(vinfos, new BMDVInfo { material = nextMaterial, uv = new Vec2 { x = input.u[input.c_uv[i]], y = input.v[input.c_uv[i]] }, normal = new Vec3 { x = input.nx[input.c_norm[i]], y = input.ny[input.c_norm[i]], z = input.nz[input.c_norm[i]] } }, vi); } nextMaterial++; return new CSGModel(verts, vinfos); }
public static CSGModel ModelFromBMD(BasicModelData input, Mat4 xform) { List <Vec3> verts = new List <Vec3>(); List <VInfo> vinfos = new List <VInfo>(); CopyAndTransformVert vx = VertexTransformationByMat4(xform); CopyAndTransformVInfo vi = BMDVInfoTransformationByMat4(xform); for (int i = 0; i < input.a_vert.Length; i++) { TransformAndAddVec3(verts, new Vec3 { x = input.x[input.a_vert[i]], y = input.y[input.a_vert[i]], z = input.z[input.a_vert[i]] }, vx); TransformAndAddVec3(verts, new Vec3 { x = input.x[input.b_vert[i]], y = input.y[input.b_vert[i]], z = input.z[input.b_vert[i]] }, vx); TransformAndAddVec3(verts, new Vec3 { x = input.x[input.c_vert[i]], y = input.y[input.c_vert[i]], z = input.z[input.c_vert[i]] }, vx); TransformAndAddVInfo(vinfos, new BMDVInfo { material = nextMaterial, uv = new Vec2 { x = input.u[input.a_uv[i]], y = input.v[input.a_uv[i]] }, normal = new Vec3 { x = input.nx[input.a_norm[i]], y = input.ny[input.a_norm[i]], z = input.nz[input.a_norm[i]] } }, vi); TransformAndAddVInfo(vinfos, new BMDVInfo { material = nextMaterial, uv = new Vec2 { x = input.u[input.b_uv[i]], y = input.v[input.b_uv[i]] }, normal = new Vec3 { x = input.nx[input.b_norm[i]], y = input.ny[input.b_norm[i]], z = input.nz[input.b_norm[i]] } }, vi); TransformAndAddVInfo(vinfos, new BMDVInfo { material = nextMaterial, uv = new Vec2 { x = input.u[input.c_uv[i]], y = input.v[input.c_uv[i]] }, normal = new Vec3 { x = input.nx[input.c_norm[i]], y = input.ny[input.c_norm[i]], z = input.nz[input.c_norm[i]] } }, vi); } nextMaterial++; return(new CSGModel(verts, vinfos)); }
public static CSGModel ModelFromBMD(BasicModelData input) { return ModelFromBMD(input, Mat4.Identity); }
// Makes a ModelInput object from a BasicModelData object (with verts and normals transformed by the 4x4 xform matrix) public static ModelInput FromBasicModelData(BasicModelData data, Mat4 xform) { List<Vec3> verts = new List<Vec3>(); List<int> vertMapping = new List<int>(); for (int i = 0; i < data.x.Length; i++) { Vec3 vert = xform.TransformVec3(new Vec3 { x = data.x[i], y = data.y[i], z = data.z[i] }, 1.0); int index = verts.FindIndex(vec => vec.x == vert.x && vec.y == vert.y && vec.z == vert.z); if (index == -1) { vertMapping.Add(verts.Count); verts.Add(vert); } else vertMapping.Add(index); } int[][] t_v_indices = new int[data.a_vert.Length][]; for (int i = 0; i < data.a_vert.Length; i++) { int a = vertMapping[(int)data.a_vert[i]]; int b = vertMapping[(int)data.b_vert[i]]; int c = vertMapping[(int)data.c_vert[i]]; t_v_indices[i] = new int[] { a, b, c }; } return new ModelInput(verts.ToArray(), t_v_indices); }
// Function that transforms stuff and does interpolation for vertices that were created in the middles of faces // TODO: replace with a generic user-vertex-info function public static BasicModelVert WorkingVertexToBMV(Vec3 position, VInfoReference[] vinfos, BasicModelData input_model, Mat4 input_xform, WorkingModel working_model) { Vec3 normal = Vec3.Zero; Vec2 uv = Vec2.Zero; foreach (VInfoReference vinfo in vinfos) { int index = vinfo.index; if (index != -1) { int tri = index / 3; int vert = index % 3; double weight = vinfo.weight; int normal_index = (int)(vert == 0 ? input_model.a_norm[tri] : vert == 1 ? input_model.b_norm[tri] : input_model.c_norm[tri]); normal += weight * input_xform.TransformVec3(new Vec3 { x = input_model.nx[normal_index], y = input_model.ny[normal_index], z = input_model.nz[normal_index] }, 0.0); int uv_index = (int)(vert == 0 ? input_model.a_uv[tri] : vert == 1 ? input_model.b_uv[tri] : input_model.c_uv[tri]); uv += weight * new Vec2 { x = input_model.u[uv_index], y = input_model.v[uv_index] }; } } return(new BasicModelVert { position = position, normal = Vec3.Normalize(normal), uv = uv }); }
// 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); }
// 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); }
// Function that transforms stuff and does interpolation for vertices that were created in the middles of faces // TODO: replace with a generic user-vertex-info function public static BasicModelVert WorkingVertexToBMV(Vec3 position, VInfoReference[] vinfos, BasicModelData input_model, Mat4 input_xform, WorkingModel working_model) { Vec3 normal = Vec3.Zero; Vec2 uv = Vec2.Zero; foreach (VInfoReference vinfo in vinfos) { int index = vinfo.index; if (index != -1) { int tri = index / 3; int vert = index % 3; double weight = vinfo.weight; int normal_index = (int)(vert == 0 ? input_model.a_norm[tri] : vert == 1 ? input_model.b_norm[tri] : input_model.c_norm[tri]); normal += weight * input_xform.TransformVec3(new Vec3 { x = input_model.nx[normal_index], y = input_model.ny[normal_index], z = input_model.nz[normal_index] }, 0.0); int uv_index = (int)(vert == 0 ? input_model.a_uv[tri] : vert == 1 ? input_model.b_uv[tri] : input_model.c_uv[tri]); uv += weight * new Vec2 { x = input_model.u[uv_index], y = input_model.v[uv_index] }; } } return new BasicModelVert { position = position, normal = Vec3.Normalize(normal), uv = uv }; }
public static CSGModel ModelFromBMD(BasicModelData input) { return(ModelFromBMD(input, Mat4.Identity)); }