public override void OnModuleSceneDebugGUI() { CGVMesh vmesh = Target.InData.GetData <CGVMesh>(); if (vmesh) { Handles.matrix = Target.Generator.transform.localToWorldMatrix; if (Target.ShowVertices) { CGEditorUtility.SceneGUIPlot(vmesh.Vertex, 0.1f, Color.gray); } if (Target.ShowVertexID) { var labels = Enumerable.Range(0, vmesh.Count).Select(i => i.ToString()).ToArray <string>(); CGEditorUtility.SceneGUILabels(vmesh.Vertex, labels, Color.black, Vector2.zero); } if (Target.ShowUV && vmesh.HasUV) { var labels = Enumerable.Range(0, vmesh.UV.Length - 1).Select(i => string.Format("({0:0.##},{1:0.##})", vmesh.UV[i].x, vmesh.UV[i].y)).ToArray <string>(); CGEditorUtility.SceneGUILabels(vmesh.Vertex, labels, Color.black, Vector2.zero); } Handles.matrix = Matrix4x4.identity; } }
void build(CGVMesh vmesh, CGVolume vol, IntRegion subset) { // Because each Material ID forms a submesh // Do we need to calculate localU? if (GenerateUV) { System.Array.Resize <Vector2>(ref vmesh.UV, vmesh.Count); } // Prepare Submeshes prepareSubMeshes(vmesh, groupsByMatID, subset.Length, ref m_Material); //prepareSubMeshes(vmesh, groupsByMatID, vol.Count - 1, ref m_Material); SamplePointsMaterialGroupCollection col; SamplePointsMaterialGroup grp; int vtIdx = 0; int[] triIdx = new int[groupsByMatID.Count]; // triIdx for each submesh // for all sample segments (except the last) along the path, create Triangles to the next segment for (int sample = subset.From; sample < subset.To; sample++) { // for each submesh (collection) for (int subMeshIdx = 0; subMeshIdx < groupsByMatID.Count; subMeshIdx++) { col = groupsByMatID[subMeshIdx]; // create UV and triangles for all groups in submesh for (int g = 0; g < col.Count; g++) { grp = col[g]; if (GenerateUV) { createMaterialGroupUV(ref vmesh, ref vol, ref grp, col.MaterialID, col.AspectCorrection, sample, vtIdx); } for (int p = 0; p < grp.Patches.Count; p++) { createPatchTriangles(ref vmesh.SubMeshes[subMeshIdx].Triangles, ref triIdx[subMeshIdx], vtIdx + grp.Patches[p].Start, grp.Patches[p].Count, vol.CrossSize, ReverseTriOrder); } } } vtIdx += vol.CrossSize; } // UV for last path segment if (GenerateUV) { // for each submesh (collection) for (int subMeshIdx = 0; subMeshIdx < groupsByMatID.Count; subMeshIdx++) { col = groupsByMatID[subMeshIdx]; // create triangles for (int g = 0; g < col.Count; g++) { grp = col[g]; createMaterialGroupUV(ref vmesh, ref vol, ref grp, col.MaterialID, col.AspectCorrection, subset.To, vtIdx); } } } }
void prepareSubMeshes(CGVMesh vmesh, List <SamplePointsMaterialGroupCollection> groupsBySubMeshes, int extrusions, ref Material[] materials) { vmesh.SetSubMeshCount(groupsBySubMeshes.Count); for (int g = 0; g < groupsBySubMeshes.Count; g++) { CGVSubMesh sm = vmesh.SubMeshes[g]; vmesh.SubMeshes[g] = CGVSubMesh.Get(sm, groupsBySubMeshes[g].TriangleCount * extrusions * 3, materials[Mathf.Min(groupsBySubMeshes[g].MaterialID, materials.Length - 1)]); } }
public override void OnModuleDebugGUI() { CGVMesh vmesh = Target.OutVMesh.GetData <CGVMesh>(); if (vmesh) { EditorGUILayout.LabelField("Vertices: " + vmesh.Count); EditorGUILayout.LabelField("Triangles: " + vmesh.TriangleCount); EditorGUILayout.LabelField("SubMeshes: " + vmesh.SubMeshes.Length); } }
/*! \endcond */ #endregion #region ### Public Methods ### public override void Refresh() { base.Refresh(); var vol = InVolume.GetData <CGVolume>(); if (vol && vol.Count > 0 && vol.CrossSize > 0 && vol.CrossMaterialGroups.Count > 0) { List <IntRegion> volSets = new List <IntRegion>(); if (Split) { float dist; float lastdist = 0; int lastIndex = 0; for (int sample = 0; sample < vol.Count; sample++) { dist = vol.FToDistance(vol.F[sample]); if (dist - lastdist >= SplitLength) { volSets.Add(new IntRegion(lastIndex, sample)); lastdist = dist; lastIndex = sample; } } if (lastIndex < vol.Count - 1) { volSets.Add(new IntRegion(lastIndex, vol.Count - 1)); } } else { volSets.Add(new IntRegion(0, vol.Count - 1)); } CGVMesh[] data = OutVMesh.GetAllData <CGVMesh>(); System.Array.Resize <CGVMesh>(ref data, volSets.Count); prepare(vol); for (int sub = 0; sub < volSets.Count; sub++) { data[sub] = CGVMesh.Get(data[sub], vol, volSets[sub], GenerateUV, ReverseTriOrder); build(data[sub], vol, volSets[sub]); } OutVMesh.SetData(data); } else { OutVMesh.SetData(null); } }
/// <summary> /// create a mesh resource and copy vmesh data to the mesh! /// </summary> /// <param name="vmesh"></param> CGMeshResource writeVMeshToMesh(ref CGVMesh vmesh) { CGMeshResource res; Mesh mesh; bool wantNormals = (AddNormals != CGYesNoAuto.No); bool wantTangents = (AddTangents != CGYesNoAuto.No); res = getNewMesh(); #if UNITY_EDITOR if (!Application.isPlaying) { res.Filter.gameObject.isStatic = false; } #endif mesh = res.Prepare(); res.gameObject.layer = Layer; vmesh.ToMesh(ref mesh); VertexCount += vmesh.Count; if (AddUV2 && !vmesh.HasUV2) { mesh.uv2 = CGUtility.CalculateUV2(vmesh.UV); } if (wantNormals && !vmesh.HasNormals) { mesh.RecalculateNormals(); } if (wantTangents && !vmesh.HasTangents) { res.Filter.CalculateTangents(); } // Reset Transform res.Filter.transform.localPosition = Vector3.zero; res.Filter.transform.localRotation = Quaternion.identity; res.Filter.transform.localScale = Vector3.one; #if UNITY_EDITOR if (!Application.isPlaying) { res.Filter.gameObject.isStatic = MakeStatic; } #endif res.Renderer.sharedMaterials = vmesh.GetMaterials(); return(res); }
/*! \cond PRIVATE */ void createMeshes(ref List <CGVMesh> vMeshes, bool combine) { int exceededVertexCount = 0; if (combine) { sortByVertexCount(ref vMeshes); // Skip meshes that exceeds Vertex limits while (vMeshes[exceededVertexCount].Count > 65534) { exceededVertexCount++; } CGVMesh curVMesh = (vMeshes.Count == 1) ? vMeshes[0] : new CGVMesh(vMeshes[0]); // Just one mesh? No need to create a copy! Otherwise, take a copy! for (int vm = exceededVertexCount + 1; vm < vMeshes.Count; vm++) { if (curVMesh.Count + vMeshes[vm].Count > 65534) { // write curVMesh writeVMeshToMesh(ref curVMesh); curVMesh = (vm < vMeshes.Count - 1) ? vMeshes[vm] : new CGVMesh(vMeshes[vm]); // just one mesh left? No need to create a copy! Otherwise, take a copy! } else // Add new vMesh to curVMesh { curVMesh.MergeVMesh(vMeshes[vm]); } } writeVMeshToMesh(ref curVMesh); } else { for (int vm = 0; vm < vMeshes.Count; vm++) { if (vMeshes[vm].Count < 65535) { CGVMesh vmesh = vMeshes[vm]; writeVMeshToMesh(ref vmesh); } else { exceededVertexCount++; } } } if (exceededVertexCount > 0) { UIMessages.Add(string.Format("{0} meshes skipped (VertexCount>65534)", exceededVertexCount)); } }
/*! \endcond */ #endregion #region ### Public Methods ### public override void Refresh() { base.Refresh(); //OutVMesh if (OutVMesh.IsLinked) { var data = new CGVMesh[Meshes.Count]; int total = 0; for (int i = 0; i < Meshes.Count; i++) { if (Meshes[i].Mesh) { data[total++] = new CGVMesh(Meshes[i]); } } System.Array.Resize <CGVMesh>(ref data, total); OutVMesh.SetData(data); } }
/*! \endcond */ #endregion #region ### Public Methods ### public override void Refresh() { base.Refresh(); //OutVMesh if (OutVMesh.IsLinked) { var data = new CGVMesh[Meshes.Count]; int total = 0; for (int i = 0; i < Meshes.Count; i++) { if (Meshes[i].Mesh) { data[total++] = new CGVMesh(Meshes[i]); } } System.Array.Resize<CGVMesh>(ref data, total); OutVMesh.SetData(data); } }
// OPTIMIZE: Store array of U values and just copy them void createMaterialGroupUV(ref CGVMesh vmesh, ref CGVolume vol, ref SamplePointsMaterialGroup grp, int matIndex, float grpAspectCorrection, int sample, int baseVertex) { var mat = m_MaterialSettings[matIndex]; float v = mat.UVOffset.y + vol.F[sample] * mat.UVScale.y * grpAspectCorrection; float u; int hi = grp.EndVertex; for (int c = grp.StartVertex; c <= hi; c++) { u = mat.UVOffset.x + vol.CrossMap[c] * mat.UVScale.x; if (mat.SwapUV) { vmesh.UV[baseVertex + c] = new Vector2(v, u); } else { vmesh.UV[baseVertex + c] = new Vector2(u, v); } } }
void build(CGVMesh vmesh, CGVolume vol, IntRegion subset) { // Because each Material ID forms a submesh // Do we need to calculate localU? if (GenerateUV) { System.Array.Resize<Vector2>(ref vmesh.UV, vmesh.Count); } // Prepare Submeshes prepareSubMeshes(vmesh, groupsByMatID, subset.Length, ref m_Material); //prepareSubMeshes(vmesh, groupsByMatID, vol.Count - 1, ref m_Material); SamplePointsMaterialGroupCollection col; SamplePointsMaterialGroup grp; int vtIdx = 0; int[] triIdx = new int[groupsByMatID.Count]; // triIdx for each submesh // for all sample segments (except the last) along the path, create Triangles to the next segment for (int sample = subset.From; sample < subset.To; sample++) { // for each submesh (collection) for (int subMeshIdx = 0; subMeshIdx < groupsByMatID.Count; subMeshIdx++) { col = groupsByMatID[subMeshIdx]; // create UV and triangles for all groups in submesh for (int g = 0; g < col.Count; g++) { grp = col[g]; if (GenerateUV) createMaterialGroupUV(ref vmesh, ref vol, ref grp, col.MaterialID, col.AspectCorrection, sample, vtIdx); for (int p = 0; p < grp.Patches.Count; p++) createPatchTriangles(ref vmesh.SubMeshes[subMeshIdx].Triangles, ref triIdx[subMeshIdx], vtIdx+grp.Patches[p].Start, grp.Patches[p].Count, vol.CrossSize, ReverseTriOrder); } } vtIdx += vol.CrossSize; } // UV for last path segment if (GenerateUV) { // for each submesh (collection) for (int subMeshIdx = 0; subMeshIdx < groupsByMatID.Count; subMeshIdx++) { col = groupsByMatID[subMeshIdx]; // create triangles for (int g = 0; g < col.Count; g++) { grp = col[g]; createMaterialGroupUV(ref vmesh, ref vol, ref grp, col.MaterialID, col.AspectCorrection, subset.To, vtIdx); } } } }
void createSpotMeshes(ref List <CGVMesh> vMeshes, ref CGSpots spots, bool combine) { int exceededVertexCount = 0; int vmCount = vMeshes.Count; CGSpot spot; CGMeshResource res; if (combine) { var sortedSpots = new List <CGSpot>(spots.Points); if (GroupMeshes) { sortedSpots.Sort((CGSpot a, CGSpot b) => a.Index.CompareTo(b.Index)); } spot = sortedSpots[0]; CGVMesh curVMesh = new CGVMesh(vMeshes[spot.Index]); if (spot.Position != Vector3.zero || spot.Rotation != Quaternion.identity || spot.Scale != Vector3.one) { curVMesh.TRS(spot.Matrix); } for (int s = 1; s < sortedSpots.Count; s++) { spot = sortedSpots[s]; // Filter spot.index not in vMeshes[] if (spot.Index > -1 && spot.Index < vmCount) { if (curVMesh.Count + vMeshes[spot.Index].Count > 65534 || (GroupMeshes && spot.Index != sortedSpots[s - 1].Index)) { // write curVMesh writeVMeshToMesh(ref curVMesh); curVMesh = new CGVMesh(vMeshes[spot.Index]); if (!spot.Matrix.isIdentity) { curVMesh.TRS(spot.Matrix); } } else { // Add new vMesh to curVMesh if (!spot.Matrix.isIdentity) { curVMesh.MergeVMesh(vMeshes[spot.Index], spot.Matrix); } else { curVMesh.MergeVMesh(vMeshes[spot.Index]); } } } } writeVMeshToMesh(ref curVMesh); } else { for (int s = 0; s < spots.Count; s++) { spot = spots.Points[s]; // Filter spot.index not in vMeshes[] if (spot.Index > -1 && spot.Index < vmCount) { // Don't touch vertices, TRS Resource instead if (vMeshes[spot.Index].Count < 65535) { CGVMesh vmesh = vMeshes[spot.Index]; res = writeVMeshToMesh(ref vmesh); if (spot.Position != Vector3.zero || spot.Rotation != Quaternion.identity || spot.Scale != Vector3.one) { spot.ToTransform(res.Filter.transform); } } else { exceededVertexCount++; } } } } if (exceededVertexCount > 0) { UIMessages.Add(string.Format("{0} meshes skipped (VertexCount>65534)", exceededVertexCount)); } }
// OPTIMIZE: Store array of U values and just copy them void createMaterialGroupUV(ref CGVMesh vmesh, ref CGVolume vol, ref SamplePointsMaterialGroup grp, int matIndex, float grpAspectCorrection, int sample, int baseVertex) { var mat = m_MaterialSettings[matIndex]; float v = mat.UVOffset.y + vol.F[sample] * mat.UVScale.y * grpAspectCorrection; float u; int hi = grp.EndVertex; for (int c = grp.StartVertex; c <= hi; c++) { u = mat.UVOffset.x + vol.CrossMap[c] * mat.UVScale.x; if (mat.SwapUV) vmesh.UV[baseVertex+c] = new Vector2(v, u); else vmesh.UV[baseVertex+c] = new Vector2(u, v); } }
/*! \endcond */ #endregion #region ### Public Methods ### public override void Refresh() { base.Refresh(); CGVolume vol = InVolume.GetData <CGVolume>(); var holes = InVolumeHoles.GetAllData <CGVolume>(); if (vol) { bool genStart = (StartCap == CGYesNoAuto.Yes || (StartCap == CGYesNoAuto.Auto && !vol.Seamless)); bool genEnd = (EndCap == CGYesNoAuto.Yes || (EndCap == CGYesNoAuto.Auto && !vol.Seamless)); if (!genStart && !genEnd) { OutVMesh.SetData(null); return; } var vmesh = new CGVMesh(); Vector3[] vtStart = new Vector3[0]; Vector3[] vtEnd = new Vector3[0]; Polygon pOuter; vmesh.AddSubMesh(new CGVSubMesh()); CGVSubMesh submesh = vmesh.SubMeshes[0]; Vector3[] points; if (genStart) { #region --- Start Cap --- points = make2DSegment(vol, 0); if (points.Length < 3) { OutVMesh.SetData(null); UIMessages.Add("Cross has <3 Vertices: Can't create Caps!"); return; } pOuter = new Polygon(points); for (int h = 0; h < holes.Count; h++) { points = make2DSegment(holes[h], 0); if (points.Length < 3) { OutVMesh.SetData(null); UIMessages.Add("Hole Cross has <3 Vertices: Can't create Caps!"); return; } pOuter.AddHole(new Polygon(points)); } try { P2T.Triangulate(pOuter); } catch (System.Exception e) { Debug.LogException(e); OutVMesh.SetData(null); return; } submesh.Material = StartMaterial; pOuter.GetResults(out vtStart, out submesh.Triangles, ReverseTriOrder); vmesh.Vertex = applyMat(vtStart, getMat(vol, 0, true)); if (GenerateUV) { vmesh.UV = new Vector2[vtStart.Length]; applyUV(vtStart, ref vmesh.UV, 0, vtStart.Length, pOuter.Bounds.Bounds, StartMaterialSettings); } #endregion } if (genEnd) { #region --- End Cap --- points = make2DSegment(vol, vol.Count - 1); if (points.Length < 3) { OutVMesh.SetData(null); UIMessages.Add("Cross has <3 Vertices: Can't create Caps!"); return; } pOuter = new Polygon(points); for (int h = 0; h < holes.Count; h++) { points = make2DSegment(holes[h], holes[h].Count - 1); if (points.Length < 3) { OutVMesh.SetData(null); UIMessages.Add("Hole Cross has <3 Vertices: Can't create Caps!"); return; } pOuter.AddHole(new Polygon(points)); } try { P2T.Triangulate(pOuter); } catch (System.Exception e) { Debug.LogException(e); OutVMesh.SetData(null); return; } int[] tris; pOuter.GetResults(out vtEnd, out tris, !ReverseTriOrder, vtStart.Length); vmesh.Vertex = vmesh.Vertex.AddRange <Vector3>(applyMat(vtEnd, getMat(vol, vol.Count - 1, true))); if (!CloneStartCap && StartMaterial != EndMaterial) { vmesh.AddSubMesh(new CGVSubMesh(tris, EndMaterial)); } else { submesh.Material = StartMaterial; submesh.Triangles = submesh.Triangles.AddRange <int>(tris); } if (GenerateUV) { System.Array.Resize <Vector2>(ref vmesh.UV, vmesh.UV.Length + vtEnd.Length); applyUV(vtEnd, ref vmesh.UV, vtStart.Length, vtEnd.Length, pOuter.Bounds.Bounds, (CloneStartCap) ? StartMaterialSettings : EndMaterialSettings); } #endregion } OutVMesh.SetData(vmesh); } }
/*! \endcond */ #endregion #region ### Public Methods ### public override void Refresh() { base.Refresh(); CGVolume vol = InVolume.GetData <CGVolume>(); var holes = InVolumeHoles.GetAllData <CGVolume>(); if (vol) { bool genStart = (StartCap == CGYesNoAuto.Yes || (StartCap == CGYesNoAuto.Auto && !vol.Seamless)); bool genEnd = (EndCap == CGYesNoAuto.Yes || (EndCap == CGYesNoAuto.Auto && !vol.Seamless)); if (!genStart && !genEnd) { OutVMesh.SetData(null); return; } var vmesh = new CGVMesh(); Vector3[] vtStart = new Vector3[0]; Vector3[] vtEnd = new Vector3[0]; vmesh.AddSubMesh(new CGVSubMesh()); CGVSubMesh submesh = vmesh.SubMeshes[0]; if (genStart) { #region --- Start Cap --- var tess = new Tess(); tess.UsePooling = true; tess.AddContour(make2DSegment(vol, 0)); for (int h = 0; h < holes.Count; h++) { if (holes[h].Count < 3) { OutVMesh.SetData(null); UIMessages.Add("Hole Cross has <3 Vertices: Can't create Caps!"); return; } tess.AddContour(make2DSegment(holes[h], 0)); } tess.Tessellate(WindingRule.EvenOdd, ElementType.Polygons, 3); vtStart = UnityLibTessUtility.FromContourVertex(tess.Vertices); Bounds b; vmesh.Vertex = applyMat(vtStart, getMat(vol, 0, true), out b); submesh.Material = StartMaterial; submesh.Triangles = tess.Elements; if (ReverseTriOrder) { flipTris(ref submesh.Triangles, 0, submesh.Triangles.Length); } if (GenerateUV) { vmesh.UV = new Vector2[vtStart.Length]; applyUV(vtStart, ref vmesh.UV, 0, vtStart.Length, StartMaterialSettings, b); } #endregion } if (genEnd) { #region --- End Cap --- var tess = new Tess(); tess.UsePooling = true; tess.AddContour(make2DSegment(vol, 0)); for (int h = 0; h < holes.Count; h++) { if (holes[h].Count < 3) { OutVMesh.SetData(null); UIMessages.Add("Hole Cross has <3 Vertices: Can't create Caps!"); return; } tess.AddContour(make2DSegment(holes[h], 0)); } tess.Tessellate(WindingRule.EvenOdd, ElementType.Polygons, 3); vtEnd = UnityLibTessUtility.FromContourVertex(tess.Vertices); Bounds b; int l = vmesh.Vertex.Length; vmesh.Vertex = vmesh.Vertex.AddRange <Vector3>(applyMat(vtEnd, getMat(vol, vol.Count - 1, true), out b)); int[] tris = tess.Elements; if (!ReverseTriOrder) { flipTris(ref tris, 0, tris.Length); } for (int i = 0; i < tris.Length; i++) { tris[i] += l; } if (!CloneStartCap && StartMaterial != EndMaterial) { vmesh.AddSubMesh(new CGVSubMesh(tris, EndMaterial)); } else { submesh.Material = StartMaterial; submesh.Triangles = submesh.Triangles.AddRange <int>(tris); } if (GenerateUV) { System.Array.Resize <Vector2>(ref vmesh.UV, vmesh.UV.Length + vtEnd.Length); applyUV(vtEnd, ref vmesh.UV, vtStart.Length, vtEnd.Length, (CloneStartCap) ? StartMaterialSettings : EndMaterialSettings, b); } #endregion } OutVMesh.SetData(vmesh); } }
void prepareSubMeshes(CGVMesh vmesh, List<SamplePointsMaterialGroupCollection> groupsBySubMeshes, int extrusions, ref Material[] materials) { vmesh.SetSubMeshCount(groupsBySubMeshes.Count); for (int g = 0; g < groupsBySubMeshes.Count; g++) { CGVSubMesh sm = vmesh.SubMeshes[g]; vmesh.SubMeshes[g] = CGVSubMesh.Get(sm, groupsBySubMeshes[g].TriangleCount * extrusions * 3, materials[Mathf.Min(groupsBySubMeshes[g].MaterialID, materials.Length - 1)]); } }
/*! \endcond */ #endregion #region ### Public Methods ### public override void Refresh() { base.Refresh(); CGVolume vol = InVolume.GetData<CGVolume>(); var holes = InVolumeHoles.GetAllData<CGVolume>(); if (vol) { bool genStart = (StartCap == CGYesNoAuto.Yes || (StartCap == CGYesNoAuto.Auto && !vol.Seamless)); bool genEnd = (EndCap == CGYesNoAuto.Yes || (EndCap == CGYesNoAuto.Auto && !vol.Seamless)); if (!genStart && !genEnd) { OutVMesh.SetData(null); return; } var vmesh = new CGVMesh(); Vector3[] vtStart = new Vector3[0]; Vector3[] vtEnd = new Vector3[0]; Polygon pOuter; vmesh.AddSubMesh(new CGVSubMesh()); CGVSubMesh submesh = vmesh.SubMeshes[0]; Vector3[] points; if (genStart) { #region --- Start Cap --- points = make2DSegment(vol, 0); if (points.Length < 3) { OutVMesh.SetData(null); UIMessages.Add("Cross has <3 Vertices: Can't create Caps!"); return; } pOuter = new Polygon(points); for (int h = 0; h < holes.Count; h++) { points = make2DSegment(holes[h], 0); if (points.Length < 3) { OutVMesh.SetData(null); UIMessages.Add("Hole Cross has <3 Vertices: Can't create Caps!"); return; } pOuter.AddHole(new Polygon(points)); } try { P2T.Triangulate(pOuter); } catch (System.Exception e) { Debug.LogException(e); OutVMesh.SetData(null); return; } submesh.Material = StartMaterial; pOuter.GetResults(out vtStart, out submesh.Triangles, ReverseTriOrder); vmesh.Vertex = applyMat(vtStart, getMat(vol, 0, true)); if (GenerateUV) { vmesh.UV = new Vector2[vtStart.Length]; applyUV(vtStart, ref vmesh.UV, 0, vtStart.Length, pOuter.Bounds.Bounds, StartMaterialSettings); } #endregion } if (genEnd) { #region --- End Cap --- points = make2DSegment(vol, vol.Count - 1); if (points.Length < 3) { OutVMesh.SetData(null); UIMessages.Add("Cross has <3 Vertices: Can't create Caps!"); return; } pOuter = new Polygon(points); for (int h = 0; h < holes.Count; h++) { points = make2DSegment(holes[h], holes[h].Count - 1); if (points.Length < 3) { OutVMesh.SetData(null); UIMessages.Add("Hole Cross has <3 Vertices: Can't create Caps!"); return; } pOuter.AddHole(new Polygon(points)); } try { P2T.Triangulate(pOuter); } catch (System.Exception e) { Debug.LogException(e); OutVMesh.SetData(null); return; } int[] tris; pOuter.GetResults(out vtEnd, out tris, !ReverseTriOrder, vtStart.Length); vmesh.Vertex = vmesh.Vertex.AddRange<Vector3>(applyMat(vtEnd, getMat(vol, vol.Count - 1, true))); if (!CloneStartCap && StartMaterial != EndMaterial) { vmesh.AddSubMesh(new CGVSubMesh(tris, EndMaterial)); } else { submesh.Material = StartMaterial; submesh.Triangles = submesh.Triangles.AddRange<int>(tris); } if (GenerateUV) { System.Array.Resize<Vector2>(ref vmesh.UV, vmesh.UV.Length + vtEnd.Length); applyUV(vtEnd, ref vmesh.UV, vtStart.Length, vtEnd.Length, pOuter.Bounds.Bounds, (CloneStartCap) ? StartMaterialSettings : EndMaterialSettings); } #endregion } OutVMesh.SetData(vmesh); } }
/// <summary> /// create a mesh resource and copy vmesh data to the mesh! /// </summary> /// <param name="vmesh"></param> CGMeshResource writeVMeshToMesh(ref CGVMesh vmesh) { CGMeshResource res; Mesh mesh; bool wantNormals = (AddNormals != CGYesNoAuto.No); bool wantTangents = (AddTangents != CGYesNoAuto.No); res = getNewMesh(); #if UNITY_EDITOR if (!Application.isPlaying) res.Filter.gameObject.isStatic = false; #endif mesh = res.Prepare(); res.gameObject.layer = Layer; vmesh.ToMesh(ref mesh); VertexCount += vmesh.Count; if (AddUV2 && !vmesh.HasUV2) mesh.uv2 = CGUtility.CalculateUV2(vmesh.UV); if (wantNormals && !vmesh.HasNormals) mesh.RecalculateNormals(); if (wantTangents && !vmesh.HasTangents) res.Filter.CalculateTangents(); // Reset Transform res.Filter.transform.localPosition = Vector3.zero; res.Filter.transform.localRotation = Quaternion.identity; res.Filter.transform.localScale = Vector3.one; #if UNITY_EDITOR if (!Application.isPlaying) res.Filter.gameObject.isStatic = MakeStatic; #endif res.Renderer.sharedMaterials = vmesh.GetMaterials(); return res; }
void createSpotMeshes(ref List<CGVMesh> vMeshes, ref CGSpots spots, bool combine) { int exceededVertexCount = 0; int vmCount = vMeshes.Count; CGSpot spot; CGMeshResource res; if (combine) { var sortedSpots = new List<CGSpot>(spots.Points); if (GroupMeshes) sortedSpots.Sort((CGSpot a, CGSpot b) => a.Index.CompareTo(b.Index)); spot = sortedSpots[0]; CGVMesh curVMesh = new CGVMesh(vMeshes[spot.Index]); if (spot.Position != Vector3.zero || spot.Rotation != Quaternion.identity || spot.Scale != Vector3.one) curVMesh.TRS(spot.Matrix); for (int s = 1; s < sortedSpots.Count; s++) { spot = sortedSpots[s]; // Filter spot.index not in vMeshes[] if (spot.Index > -1 && spot.Index < vmCount) { if (curVMesh.Count + vMeshes[spot.Index].Count > 65534 || (GroupMeshes && spot.Index != sortedSpots[s - 1].Index)) { // write curVMesh writeVMeshToMesh(ref curVMesh); curVMesh = new CGVMesh(vMeshes[spot.Index]); if (!spot.Matrix.isIdentity) curVMesh.TRS(spot.Matrix); } else { // Add new vMesh to curVMesh if (!spot.Matrix.isIdentity) curVMesh.MergeVMesh(vMeshes[spot.Index], spot.Matrix); else curVMesh.MergeVMesh(vMeshes[spot.Index]); } } } writeVMeshToMesh(ref curVMesh); } else { for (int s = 0; s < spots.Count; s++) { spot = spots.Points[s]; // Filter spot.index not in vMeshes[] if (spot.Index > -1 && spot.Index < vmCount) { // Don't touch vertices, TRS Resource instead if (vMeshes[spot.Index].Count < 65535) { CGVMesh vmesh = vMeshes[spot.Index]; res = writeVMeshToMesh(ref vmesh); if (spot.Position != Vector3.zero || spot.Rotation != Quaternion.identity || spot.Scale != Vector3.one) spot.ToTransform(res.Filter.transform); } else exceededVertexCount++; } } } if (exceededVertexCount > 0) UIMessages.Add(string.Format("{0} meshes skipped (VertexCount>65534)", exceededVertexCount)); }