public override void Update() { base.begin_update(); int start_timestamp = this.CurrentInputTimestamp; if (MeshSource == null) { throw new Exception("ReprojectOp: must set valid MeshSource to compute!"); } try { if (ReprojectMode == ReprojectModes.SmoothSurfaceFlow) { ResultMesh = compute_smooth(); } else if (ReprojectMode == ReprojectModes.SharpEdgesFlow) { ResultMesh = compute_sharp_edge_flow(); } else { ResultMesh = compute_bounded_distance(); } base.complete_update(); } catch (Exception e) { PostOnOperatorException(e); ResultMesh = base.make_failure_output(MeshSource.GetDMeshUnsafe()); base.complete_update(); } }
public virtual void Update() { base.begin_update(); if (MeshSource == null) { throw new Exception("ExtrudeMeshOp: must set valid MeshSource to compute!"); } IMesh meshIn = MeshSource.GetIMesh(); //ISpatial spatialIn = MeshSource.GetSpatial(); ExtrudedMesh = new DMesh3(meshIn, MeshHints.None); MeshExtrudeMesh extrude = new MeshExtrudeMesh(ExtrudedMesh); extrude.ExtrudedPositionF = (v, n, vid) => { return(v + extrude_dist * (Vector3d)n); }; extrude.Extrude(); ApplyModifiers(ExtrudedMesh); base.complete_update(); }
public virtual void Update() { base.begin_update(); int start_timestamp = this.CurrentInputTimestamp; if (MeshSource == null) { throw new Exception("GenerateClosedMeshOp: must set valid MeshSource to compute!"); } try { DMesh3 inputmesh = MeshSource.GetDMeshUnsafe(); ISpatial inputSpatial = MeshSource.HasSpatial ? MeshSource.GetSpatial() : null; DMeshAABBTree3 spatial = (inputSpatial != null && inputSpatial is DMeshAABBTree3) ? inputSpatial as DMeshAABBTree3 : get_cached_spatial(inputmesh); DMesh3 meshIn = new DMesh3(inputmesh); MeshRepairOrientation repair = new MeshRepairOrientation(meshIn, spatial); repair.OrientComponents(); repair.SolveGlobalOrientation(); if (invert_result) { meshIn.ReverseOrientation(true); } ResultMesh = meshIn; base.complete_update(); } catch (Exception e) { PostOnOperatorException(e); ResultMesh = base.make_failure_output(MeshSource.GetDMeshUnsafe()); base.complete_update(); } }
public virtual void Update() { base.begin_update(); if (MeshSource == null) { throw new Exception("MeshDeformationOp: must set valid MeshSource to compute!"); } IMesh meshIn = MeshSource.GetIMesh(); DMesh3 mesh = new DMesh3(meshIn, MeshHints.None); MeshNormals.QuickCompute(mesh); foreach (int vid in mesh.VertexIndices()) { Vector3d v = mesh.GetVertex(vid); Vector3f n = mesh.GetVertexNormal(vid); Vector3d newPos = deformF(v, n, vid); mesh.SetVertex(vid, newPos); } MeshNormals.QuickCompute(mesh); DisplacedMesh = mesh; base.complete_update(); }
private List <SegaSaturnPoint> GetPoints() { MeshSource positionSource = this.MeshSources.FirstOrDefault(item => item.MeshSourceKind == MeshSource.MeshSourceKindEnum.Position); if (positionSource == null) { throw new InvalidOperationException("no Position source in Collada"); } List <SegaSaturnPoint> toReturn = new List <SegaSaturnPoint>(); float coef = 1.0f; float max = positionSource.Floats.Max(); if (max < 50.0f) { coef = 50.0f / max; } else { coef = max / 50.0f; } for (int i = 0; i < positionSource.Floats.Count; i += 3) { toReturn.Add(new SegaSaturnPoint(positionSource.Floats[i + 0] * coef, positionSource.Floats[i + 1] * coef, positionSource.Floats[i + 2] * coef)); } return(toReturn); }
public virtual void Update() { base.begin_update(); if (MeshSource == null) { throw new Exception("TrimMeshFromCurveOp: must set valid MeshSource to compute!"); } if (CurveSource == null) { throw new Exception("TrimMeshFromCurveOp: must set valid CurveSource to compute!"); } IMesh meshIn = MeshSource.GetIMesh(); //ISpatial spatialIn = MeshSource.GetSpatial(); DCurve3 curve = new DCurve3(CurveSource.GetICurve()); TrimmedMesh = new DMesh3(meshIn, MeshHints.None); AxisAlignedBox3d bounds = TrimmedMesh.CachedBounds; Vector3d seed = bounds.Center + bounds.Extents.y * Vector3d.AxisY; MeshTrimLoop trim = new MeshTrimLoop(TrimmedMesh, curve, seed, null); trim.Trim(); ApplyModifiers(TrimmedMesh); base.complete_update(); }
public void BuildingWithZeroMaxTriangles_ProducesEmptyMesh() { using (var meshSource = new MeshSource(0)) { using (var builder = meshSource.GetBuilder()) builder.AddTriangle(Vector3.zero, Vector3.forward, Vector3.one); AssertEmptyMesh(meshSource.Mesh); } }
private List <SegaSaturnTexture> GetTextures(List <Texture> textureLibrary, List <SegaSaturnAttribute> attributes, int maxTextureSize) { if (textureLibrary == null || textureLibrary.Count <= 0) { return(new List <SegaSaturnTexture>()); } if (textureLibrary.Count > 1) { MessageBox.Show("Sorry, only one texture per file are supported yet :'(", Editor.Instance.Text, MessageBoxButtons.OK, MessageBoxIcon.Error); throw new InvalidOperationException("Too many textures"); } MeshSource textureSource = this.MeshSources.FirstOrDefault(item => item.MeshSourceKind == MeshSource.MeshSourceKindEnum.Texcoord); if (textureSource == null) { return(new List <SegaSaturnTexture>()); } List <SegaSaturnTexture> toReturn = new List <SegaSaturnTexture>(); Dictionary <string, SegaSaturnTexture> dict = new Dictionary <string, SegaSaturnTexture>(); List <SegaSaturnTextureVerticesIndexes> list = this.GetTextureVerticesIndexes(); Texture tmp = textureLibrary.First(); Bitmap img = JoMapEditorTools.GetBitmap(tmp.Path); if (img.Width > maxTextureSize && img.Height > maxTextureSize) { img = JoMapEditorTools.ResizeImage(img, maxTextureSize, maxTextureSize); } else if (img.Width > maxTextureSize) { img = JoMapEditorTools.ResizeImage(img, maxTextureSize, img.Height); } else if (img.Height > maxTextureSize) { img = JoMapEditorTools.ResizeImage(img, img.Width, maxTextureSize); } for (int i = 0; i < list.Count; ++i) { SegaSaturnTextureCoordinates p1 = Geometry.ConvertToSegaSaturnTextureCoordinates(img, textureSource.Floats, list[i].Vertice1); SegaSaturnTextureCoordinates p2 = Geometry.ConvertToSegaSaturnTextureCoordinates(img, textureSource.Floats, list[i].Vertice2); SegaSaturnTextureCoordinates p3 = Geometry.ConvertToSegaSaturnTextureCoordinates(img, textureSource.Floats, list[i].Vertice3); SegaSaturnTextureCoordinates p4 = Geometry.ConvertToSegaSaturnTextureCoordinates(img, textureSource.Floats, list[i].Vertice4); if (p1.Hash == p2.Hash && p2.Hash == p3.Hash) { continue; } SegaSaturnTexture texture = SegaSaturnTexture.ConvertFrom(img, tmp.Name ?? Path.GetFileNameWithoutExtension(tmp.Path), p1, p2, p3, p4, list[i].IsTriangleMapping); if (!dict.ContainsKey(texture.Hash)) { texture.Name += toReturn.Count.ToString(); dict.Add(texture.Hash, texture); toReturn.Add(texture); } attributes[i].SpriteIndex = toReturn.FindIndex(item => item.Hash == texture.Hash); attributes[i].Color = null; } return(toReturn); }
public void OnEnable() { this.source = this.GetMeshSource(); if (this.original.IsNull()) { this.original = this.GetMesh(); } this.needsUpdate = true; }
public void BuildingWithExcessiveMaxTriangles_ProducesValidMesh() { using (var meshSource = new MeshSource(24)) { var bounds = new Bounds(new Vector3(0.5f, 0.5f, 0.5f), Vector3.one); using (var builder = meshSource.GetBuilder()) { builder.Bounds = bounds; builder.AddTriangle(Vector3.zero, Vector3.forward, Vector3.one); } AssertValidMesh(meshSource.Mesh, 3, 3, bounds); } }
private List <SegaSaturnNormal> GetNormals() { MeshSource normalSource = this.MeshSources.FirstOrDefault(item => item.MeshSourceKind == MeshSource.MeshSourceKindEnum.Normal); if (normalSource == null) { List <SegaSaturnNormal> toReturn = new List <SegaSaturnNormal>(); for (int i = 0; i < this.PolygonCount; ++i) { toReturn.Add(new SegaSaturnNormal(0.0f, 1.0f, 0.0f)); } return(toReturn); } if (this.GeometryType == GeometryTypeEnum.QuadPolylist) { List <SegaSaturnNormal> toReturn = new List <SegaSaturnNormal>(); int i = normalSource.IndexOffset; while (i < this.VertexIndexes.Count) { int index = this.VertexIndexes[i]; toReturn.Add(new SegaSaturnNormal(normalSource.Floats[index], normalSource.Floats[index + 1], normalSource.Floats[index + 2])); i += (this.IndexOffsetRange + 1) * 4; } return(toReturn); } if (this.GeometryType == GeometryTypeEnum.Polygons) { int vcountIndex = 0; List <SegaSaturnNormal> toReturn = new List <SegaSaturnNormal>(); int i = normalSource.IndexOffset; while (i < this.VertexIndexes.Count) { int index = this.VertexIndexes[i]; toReturn.Add(new SegaSaturnNormal(normalSource.Floats[index], normalSource.Floats[index + 1], normalSource.Floats[index + 2])); i += (this.IndexOffsetRange + 1) * this.VertexCount[vcountIndex]; ++vcountIndex; } return(toReturn); } else { List <SegaSaturnNormal> toReturn = new List <SegaSaturnNormal>(); int i = normalSource.IndexOffset; while (i < this.VertexIndexes.Count) { int index = this.VertexIndexes[i]; toReturn.Add(new SegaSaturnNormal(normalSource.Floats[index], normalSource.Floats[index + 1], normalSource.Floats[index + 2])); i += (this.IndexOffsetRange + 1) * 3; } return(toReturn); } }
public void ExportMesh(Mesh mesh, PrefabContext prefabContext) { if (!_engine.Options.ExportMeshes) { return; } var meshSource = new MeshSource(mesh); var mdlFilePath = EvaluateMeshName(mesh, prefabContext); var assetKey = mesh.GetKey(); var lastWriteDateTimeUtc = ExportUtils.GetLastWriteTimeUtc(mesh); ExportMeshModel(meshSource, mdlFilePath, assetKey, lastWriteDateTimeUtc); }
public void BuildingWithInsufficientMaxTriangles_ProducesValidMeshWithLimitedSize() { using (var meshSource = new MeshSource(1)) { var bounds = new Bounds(new Vector3(0.5f, 0.5f, 0.5f), Vector3.one); using (var builder = meshSource.GetBuilder()) { builder.Bounds = bounds; builder.AddTriangle(Vector3.zero, Vector3.forward, Vector3.one); builder.AddTriangle(Vector3.one, Vector3.forward + Vector3.one, Vector3.one + Vector3.one); } AssertValidMesh(meshSource.Mesh, 3, 3, bounds); } }
private void SetVertices(InputLocalOffset input, int[] p, int stepSize, Dictionary <string, MeshSource> sources, DAEVertexDescription[] outputVertices) { if (input.semantic.Equals("VERTEX")) { MeshSource meshSource = sources[DAEUtils.GetUrl(input.source).Id]; for (int i = 0; i < outputVertices.Length; i++) { int idx = p[i * stepSize + (int)input.offset]; outputVertices[i].Vertex = meshSource.GetVector3(idx); } } else if (input.semantic.Equals("NORMAL")) { MeshSource meshSource = sources[DAEUtils.GetUrl(input.source).Id]; for (int i = 0; i < outputVertices.Length; i++) { int idx = p[i * stepSize + (int)input.offset]; outputVertices[i].Normal = meshSource.GetVector3(idx); } } else if (input.semantic.Equals("TEXCOORD")) { MeshSource meshSource = sources[DAEUtils.GetUrl(input.source).Id]; for (int i = 0; i < outputVertices.Length; i++) { int idx = p[i * stepSize + (int)input.offset]; outputVertices[i].TexCoord = meshSource.GetVector3(idx); outputVertices[i].TexCoord = new DAEVector3(outputVertices[i].TexCoord.X, 1 - outputVertices[i].TexCoord.Y, outputVertices[i].TexCoord.Z); } } else if (input.semantic.Equals("TEXTANGENT")) { MeshSource meshSource = sources[DAEUtils.GetUrl(input.source).Id]; for (int i = 0; i < outputVertices.Length; i++) { int idx = p[i * stepSize + (int)input.offset]; outputVertices[i].TexTangent = meshSource.GetVector3(idx); } } else if (input.semantic.Equals("TEXBINORMAL")) { MeshSource meshSource = sources[DAEUtils.GetUrl(input.source).Id]; for (int i = 0; i < outputVertices.Length; i++) { int idx = p[i * stepSize + (int)input.offset]; outputVertices[i].TexBinormal = meshSource.GetVector3(idx); } } }
public virtual void Update() { base.begin_update(); int start_timestamp = this.CurrentInputTimestamp; if (MeshSource == null) { throw new Exception("GenerateClosedMeshOp: must set valid MeshSource to compute!"); } try { DMesh3 inputmesh = MeshSource.GetDMeshUnsafe(); DMesh3 meshIn = new DMesh3(inputmesh); MeshAutoRepair repair = new MeshAutoRepair(meshIn); repair.RemoveMode = (MeshAutoRepair.RemoveModes)(int) remove_inside_mode; repair.MinEdgeLengthTol = min_edge_length; repair.ErosionIterations = erosion_iters; repair.Progress = new ProgressCancel(is_invalidated); bool bOK = repair.Apply(); if (bOK && invert_result) { meshIn.ReverseOrientation(true); } if (is_invalidated()) { meshIn = null; } if (bOK) { ResultMesh = meshIn; } else { ResultMesh = base.make_failure_output(inputmesh); } base.complete_update(); } catch (Exception e) { PostOnOperatorException(e); ResultMesh = base.make_failure_output(MeshSource.GetDMeshUnsafe()); base.complete_update(); } }
void ComputeThreadFunc(object thread_data) { thread_timestamp data = thread_data as thread_timestamp; try { DMesh3 result = MeshSource.ExtractDMesh(); lock (compute_thread_lock) { computed_result = result; computing = false; } } catch (Exception e) { background_exception = e; computing = false; last_exception_timestamp = data.timestamp; } }
private void ParseMeshSource(XmlNode meshNode, Geometry geometry) { foreach (XmlNode sourceNode in meshNode.GetElementsByTagNameCaseInsensetive("source")) { MeshSource source = new MeshSource { Id = sourceNode.GetAttributeByNameCaseInsensetive("id"), Name = sourceNode.GetAttributeByNameCaseInsensetive("name"), MeshSourceKind = MeshSource.MeshSourceKindEnum.Unknown }; XmlNode floatArrayNode = sourceNode.GetElementsByTagNameCaseInsensetive("float_array").FirstOrDefault(); if (floatArrayNode != null) { List <string> floatArray = new List <string>(floatArrayNode.InnerText.Split(new[] { " ", "\t", "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries)); source.Floats = floatArray.ConvertAll(item => float.Parse(item, CultureInfo.InvariantCulture)); geometry.MeshSources.Add(source); } } foreach (XmlNode verticesNode in meshNode.GetElementsByTagNameCaseInsensetive("vertices")) { this.ParseMeshInput(verticesNode, geometry); } }
public void ExportMesh(GameObject go, PrefabContext prefabContext) { if (!_engine.Options.ExportMeshes) { return; } var proBuilderMesh = go.GetComponent <ProBuilderMesh>(); var skinnedMeshRenderer = go.GetComponent <SkinnedMeshRenderer>(); var meshFilter = go.GetComponent <MeshFilter>(); if (proBuilderMesh != null) { ExportProBuilderMeshModel(proBuilderMesh, prefabContext); } else { Mesh mesh = null; if (skinnedMeshRenderer != null) { mesh = skinnedMeshRenderer.sharedMesh; } else if (meshFilter != null) { mesh = meshFilter.sharedMesh; } var meshSource = new MeshSource(mesh, skinnedMeshRenderer); ExportMeshModel(meshSource, EvaluateMeshName(mesh, prefabContext), mesh.GetKey(), ExportUtils.GetLastWriteTimeUtc(mesh)); } for (var i = 0; i < go.transform.childCount; ++i) { ExportMesh(go.transform.GetChild(i).gameObject, prefabContext); } }
/// <summary> /// Setup constructor /// </summary> public MeshTaggedSource( MeshSource source, string semantic ) { m_Semantic = semantic; m_Source = source; }
/// <summary> /// compute SDF for the scan object, and then compute offset iso-contours /// </summary> void compute_offset_meshes() { int sdf_cells = 128; int mesh_cells = 128; double max_offset = inner_offset + thickness; if (max_offset > cached_sdf_max_offset) { DMesh3 meshIn = new DMesh3(MeshSource.GetIMesh(), MeshHints.IsCompact, MeshComponents.None); MeshTransforms.FromFrame(meshIn, cachedInputsTransform); // [RMS] reduce this mesh? speeds up SDF quite a bit... Reducer r = new Reducer(meshIn); r.ReduceToTriangleCount(2500); double cell_size = meshIn.CachedBounds.MaxDim / sdf_cells; int exact_cells = (int)((max_offset) / cell_size) + 1; MeshSignedDistanceGrid sdf = new MeshSignedDistanceGrid(meshIn, cell_size) { ExactBandWidth = exact_cells }; sdf.Compute(); cached_sdf = sdf; cached_sdf_max_offset = max_offset; cached_sdf_bounds = meshIn.CachedBounds; cached_inner_sdf_offset = 0; cached_outer_sdf_offset = 0; } if (cached_inner_sdf_offset != inner_offset || cached_outer_sdf_offset != max_offset) { var iso = new DenseGridTrilinearImplicit(cached_sdf.Grid, cached_sdf.GridOrigin, cached_sdf.CellSize); MarchingCubes c = new MarchingCubes() { Implicit = iso }; c.Bounds = cached_sdf_bounds; c.CubeSize = c.Bounds.MaxDim / mesh_cells; c.Bounds.Expand(max_offset + 3 * c.CubeSize); if (cached_inner_sdf_offset != inner_offset) { c.IsoValue = inner_offset; c.Generate(); InnerOffsetMesh = c.Mesh; Reducer reducer = new Reducer(InnerOffsetMesh); reducer.ReduceToEdgeLength(c.CubeSize / 2); InnerOffsetMeshSpatial = new DMeshAABBTree3(InnerOffsetMesh, true); cached_inner_sdf_offset = inner_offset; } if (cached_outer_sdf_offset != max_offset) { c.IsoValue = inner_offset + thickness; c.Generate(); OuterOffsetMesh = c.Mesh; Reducer reducer = new Reducer(OuterOffsetMesh); reducer.ReduceToEdgeLength(c.CubeSize / 2); OuterOffsetMeshSpatial = new DMeshAABBTree3(OuterOffsetMesh, true); cached_outer_sdf_offset = max_offset; } } //Util.WriteDebugMesh(MeshSource.GetIMesh(), "c:\\scratch\\__OFFESTS_orig.obj"); //Util.WriteDebugMesh(InnerOffsetMesh, "c:\\scratch\\__OFFESTS_inner.obj"); //Util.WriteDebugMesh(OuterOffsetMesh, "c:\\scratch\\__OFFESTS_outer.obj"); }
public virtual void Update() { base.begin_update(); int start_timestamp = this.LastUpdateTimestamp; if (MeshSource == null) { throw new Exception("TrimMeshFromCurveOp: must set valid MeshSource to compute!"); } if (CurveSource == null) { throw new Exception("TrimMeshFromCurveOp: must set valid CurveSource to compute!"); } LocalProfiler p = new LocalProfiler(); p.Start("offset"); bool is_preview = false; // cache copy of input mesh and spatial DS DMesh3 inputMesh = MeshSource.GetDMeshUnsafe(); if (cachedInputMesh == null || input_mesh_modified_counter != input_mesh_cache_timestamp) { cachedInputMesh = new DMesh3(inputMesh, false, MeshComponents.All); cachedInputMeshSpatial = new DMeshAABBTree3(cachedInputMesh, true); input_mesh_cache_timestamp = input_mesh_modified_counter; } // have to cache this in case it changes during compute // TODO: should be caching all parameters! cachedInputsTransform = InputsTransform; // discard caches // TODO: we still have a race condition, because we could get an invalidate() between // begin_update() above and here. In that case we will be losing the cache discard flag. // Should be using update timestamp... if (pending_cache_discard) { cached_sdf_max_offset = 0; cached_inner_sdf_offset = 0; cached_outer_sdf_offset = 0; pending_cache_discard = true; } try { //compute_offset_meshes(); compute_offset_meshes_nosdf(); } catch { // we will do nothing here, let later failures handle it } p.Stop("offset"); p.Start("trim"); // trimmed mesh doesn't change unless curve changed... try { compute_trimmed_mesh(); } catch { set_failure_output(null); goto failed; } p.Stop("trim"); p.Start("inner_wall"); try { compute_inner_wall(); } catch { set_failure_output(null); goto failed; } p.Stop("inner_wall"); p.Start("outer_wall"); try { compute_outer_wall(); } catch { set_failure_output(InnerMesh); goto failed; } p.Stop("outer_wall"); p.Start("base"); is_preview = (this.CurrentInputTimestamp != start_timestamp); try { DMesh3 baseMesh = new DMesh3(SocketMesh); bool base_failed = false; do_base(baseMesh, is_preview, out base_failed); if (base_failed) { set_failure_output(SocketMesh); goto failed; } else { SocketMesh = baseMesh; } } catch (Exception e) { set_failure_output(SocketMesh); goto failed; } p.Stop("base"); f3.DebugUtil.Log(p.AllTimes()); Vector3f setColor = is_preview ? PartialSocketVertexColor : SocketVertexColor; foreach (int vid in SocketMesh.VertexIndices()) { SocketMesh.SetVertexColor(vid, setColor); } ResultMesh = SocketMesh; last_result_status = (is_preview) ? ResultStatus.PreviewResult : ResultStatus.FullResult; failed: base.complete_update(); }
public virtual void Update() { if (MeshSource == null) { throw new Exception("EnclosedRegionOffsetOp: must set valid MeshSource to compute!"); } if (MeshSource.HasSpatial == false) { throw new Exception("EnclosedRegionOffsetOp: MeshSource must have spatial data structure!"); } IMesh imesh = MeshSource.GetIMesh(); if (imesh.HasVertexNormals == false) { throw new Exception("EnclosedRegionOffsetOp: input mesh does not have surface normals..."); } if (imesh is DMesh3 == false) { throw new Exception("RegionOffsetOp: in current implementation, input mesh must be a DMesh3. Ugh."); } DMesh3 mesh = imesh as DMesh3; ISpatial spatial = MeshSource.GetSpatial(); DCurve3 curve = new DCurve3(CurveSource.GetICurve()); MeshFacesFromLoop loop = new MeshFacesFromLoop(mesh, curve, spatial); // extract submesh RegionOperator op = new RegionOperator(mesh, loop.InteriorTriangles); DMesh3 submesh = op.Region.SubMesh; // find boundary verts and nbr ring HashSet <int> boundaryV = new HashSet <int>(MeshIterators.BoundaryEdgeVertices(submesh)); HashSet <int> boundaryNbrs = new HashSet <int>(); foreach (int vid in boundaryV) { foreach (int nbrvid in submesh.VtxVerticesItr(vid)) { if (boundaryV.Contains(nbrvid) == false) { boundaryNbrs.Add(nbrvid); } } } // [TODO] maybe should be not using vertex normal here? // use an averaged normal, or a constant for patch? // offset mesh if requested if (Math.Abs(offset_distance) > 0.0001) { foreach (int vid in submesh.VertexIndices()) { if (boundaryV.Contains(vid)) { continue; } // if inner ring is non-zero, then it gets preserved below, and // creates a crease... //double dist = boundaryNbrs.Contains(vid) ? (offset_distance / 2) : offset_distance; double dist = boundaryNbrs.Contains(vid) ? 0 : offset_distance; submesh.SetVertex(vid, submesh.GetVertex(vid) + (float)dist * submesh.GetVertexNormal(vid)); } } //double t = MathUtil.Clamp(1.0 - SmoothAlpha, 0.1, 1.0); double t = 1.0 - SmoothAlpha; t = t * t; double boundary_t = 5.0; double ring_t = 1.0; // smooth submesh, with boundary-ring constraints LaplacianMeshSmoother smoother = new LaplacianMeshSmoother(submesh); foreach (int vid in submesh.VertexIndices()) { if (boundaryV.Contains(vid)) { smoother.SetConstraint(vid, submesh.GetVertex(vid), boundary_t, true); } else if (boundaryNbrs.Contains(vid)) { smoother.SetConstraint(vid, submesh.GetVertex(vid), ring_t); } else { smoother.SetConstraint(vid, submesh.GetVertex(vid), t); } } smoother.SolveAndUpdateMesh(); // turn into displacement vectors Displacement.Clear(); Displacement.Resize(mesh.MaxVertexID); foreach (int subvid in op.Region.SubMesh.VertexIndices()) { Vector3d subv = op.Region.SubMesh.GetVertex(subvid); int basevid = op.Region.SubToBaseV[subvid]; Vector3d basev = op.Region.BaseMesh.GetVertex(basevid); Displacement[basevid] = subv - basev; } result_valid = true; }
private List <SegaSaturnVertices> GetVertices() { MeshSource positionSource = this.MeshSources.FirstOrDefault(item => item.MeshSourceKind == MeshSource.MeshSourceKindEnum.Position); if (positionSource == null) { throw new InvalidOperationException("no Position source in Collada"); } if (this.GeometryType == GeometryTypeEnum.QuadPolylist) { List <SegaSaturnVertices> toReturn = new List <SegaSaturnVertices>(); int i = positionSource.IndexOffset; while (i < this.VertexIndexes.Count) { SegaSaturnVertices vertices = new SegaSaturnVertices(); vertices.Vertice1 = this.VertexIndexes[i]; i += this.IndexOffsetRange + 1; vertices.Vertice2 = this.VertexIndexes[i]; i += this.IndexOffsetRange + 1; vertices.Vertice3 = this.VertexIndexes[i]; i += this.IndexOffsetRange + 1; vertices.Vertice4 = this.VertexIndexes[i]; i += this.IndexOffsetRange + 1; toReturn.Add(vertices); } return(toReturn); } if (this.GeometryType == GeometryTypeEnum.Polygons) { int vcountIndex = 0; List <SegaSaturnVertices> toReturn = new List <SegaSaturnVertices>(); int i = positionSource.IndexOffset; while (i < this.VertexIndexes.Count) { SegaSaturnVertices vertices = new SegaSaturnVertices(); vertices.Vertice1 = this.VertexIndexes[i]; i += this.IndexOffsetRange + 1; vertices.Vertice2 = this.VertexIndexes[i]; i += this.IndexOffsetRange + 1; vertices.Vertice3 = this.VertexIndexes[i]; if (this.VertexCount[vcountIndex] == 4) { i += this.IndexOffsetRange + 1; } vertices.Vertice4 = this.VertexIndexes[i]; i += this.IndexOffsetRange + 1; toReturn.Add(vertices); ++vcountIndex; } return(toReturn); } else { List <SegaSaturnVertices> toReturn = new List <SegaSaturnVertices>(); int i = positionSource.IndexOffset; while (i < this.VertexIndexes.Count) { SegaSaturnVertices vertices = new SegaSaturnVertices(); vertices.Vertice1 = this.VertexIndexes[i]; i += this.IndexOffsetRange + 1; vertices.Vertice2 = this.VertexIndexes[i]; i += this.IndexOffsetRange + 1; vertices.Vertice3 = this.VertexIndexes[i]; vertices.Vertice4 = this.VertexIndexes[i];/*same as previous*/ i += this.IndexOffsetRange + 1; toReturn.Add(vertices); } return(toReturn); } }
public void AfterCreation_ProducesEmptyMesh() { using (var meshSource = new MeshSource(0)) { AssertEmptyMesh(meshSource.Mesh); } }
protected override void Update_GenerateMap() { base.begin_update(); if (MeshSource == null) { throw new Exception("EnclosedRegionOffsetOp: must set valid MeshSource to compute!"); } if (MeshSource.HasSpatial == false) { throw new Exception("EnclosedRegionOffsetOp: MeshSource must have spatial data structure!"); } IMesh imesh = MeshSource.GetIMesh(); if (imesh.HasVertexNormals == false) { throw new Exception("EnclosedRegionOffsetOp: input mesh does not have surface normals..."); } if (imesh is DMesh3 == false) { throw new Exception("EnclosedRegionOffsetOp: in current implementation, input mesh must be a DMesh3. Ugh."); } DMesh3 mesh = imesh as DMesh3; ISpatial spatial = MeshSource.GetSpatial(); DCurve3 curve = new DCurve3(CurveSource.GetICurve()); MeshFacesFromLoop loop = new MeshFacesFromLoop(mesh, curve, spatial); // [RMS] this is all f'n ugly! MeshVertexSelection selection = new MeshVertexSelection(mesh); selection.SelectTriangleVertices(loop.InteriorTriangles); // [TODO] do this inline w/ loop below? but then no maxdist! Dictionary <int, double> dists = new Dictionary <int, double>(); double max_dist = 0; foreach (int vid in selection) { Vector3d v = mesh.GetVertex(vid); int inearseg; double nearsegt; double min_dist_sqr = curve.DistanceSquared(v, out inearseg, out nearsegt); min_dist_sqr = Math.Sqrt(min_dist_sqr); max_dist = Math.Max(min_dist_sqr, max_dist); dists[vid] = min_dist_sqr; } lock (Displacement) { Displacement.Clear(); Displacement.Resize(mesh.MaxVertexID); // todo: can do this in parallel... foreach (int vid in selection) { //Vector3d v = mesh.GetVertex(vid); // [TODO]... double dist = max_dist - dists[vid]; double falloff = Falloff.FalloffT(dist / max_dist); Vector3d n = mesh.GetVertexNormal(vid); n = n - n.Dot(normal) * normal; n.Normalize(); Displacement[vid] = falloff * offset_distance * n; } } // smooth it? base.complete_update(); }
protected virtual DMesh3 compute_bounded_distance() { DMesh3 sourceMesh = MeshSource.GetDMeshUnsafe(); ISpatial inputSpatial = MeshSource.GetSpatial(); DMesh3 targetMesh = TargetSource.GetDMeshUnsafe(); ISpatial targetSpatial = TargetSource.GetSpatial(); double max_dist = (TargetMaxDistance == double.MaxValue) ? double.MaxValue : TargetMaxDistance; DMesh3 meshIn = new DMesh3(sourceMesh); bool target_closed = targetMesh.IsClosed(); MeshVertexSelection roiV = new MeshVertexSelection(meshIn); SpinLock roi_lock = new SpinLock(); gParallel.ForEach(meshIn.VertexIndices(), (vid) => { Vector3d pos = meshIn.GetVertex(vid); Vector3d posTarget = TransformToTarget.TransformP(pos); double dist = MeshQueries.NearestPointDistance(targetMesh, targetSpatial, posTarget, max_dist); bool inside = (target_closed && targetSpatial.IsInside(posTarget)); if (dist < max_dist || inside) { bool taken = false; roi_lock.Enter(ref taken); roiV.Select(vid); roi_lock.Exit(); } }); if (is_invalidated()) { return(null); } MeshFaceSelection roi_faces = new MeshFaceSelection(meshIn, roiV, 1); roi_faces.ExpandToOneRingNeighbours(3); roi_faces.LocalOptimize(); if (is_invalidated()) { return(null); } RegionOperator op = new RegionOperator(meshIn, roi_faces); DMesh3 meshROI = op.Region.SubMesh; if (is_invalidated()) { return(null); } RemesherPro remesher = new RemesherPro(meshROI); remesher.SetTargetEdgeLength(TargetEdgeLength); remesher.PreventNormalFlips = this.PreventNormalFlips; remesher.EnableFlips = this.EnableFlips; remesher.EnableSplits = this.EnableSplits; remesher.EnableCollapses = this.EnableCollapses; remesher.EnableSmoothing = this.EnableSmoothing; remesher.SmoothSpeedT = this.SmoothingSpeed; BoundedProjectionTarget target = new BoundedProjectionTarget() { Source = sourceMesh, SourceSpatial = inputSpatial, Target = targetMesh, TargetSpatial = targetSpatial, SourceToTargetXForm = source_to_target, TargetToSourceXForm = target_to_source, MaxDistance = max_dist, Smoothness = transition_smoothness }; remesher.SetProjectionTarget(target); if (remesher.Constraints == null) { remesher.SetExternalConstraints(new MeshConstraints()); } MeshConstraintUtil.FixAllBoundaryEdges(remesher.Constraints, meshROI); if (is_invalidated()) { return(null); } remesher.Progress = new ProgressCancel(is_invalidated); remesher.FastestRemesh(RemeshRounds); if (is_invalidated()) { return(null); } op.BackPropropagate(); return(meshIn); }
protected virtual DMesh3 compute_sharp_edge_flow() { DMesh3 sourceMesh = MeshSource.GetDMeshUnsafe(); ISpatial inputSpatial = MeshSource.GetSpatial(); DMesh3 targetMesh = TargetSource.GetDMeshUnsafe(); ISpatial targetSpatial = TargetSource.GetSpatial(); DMesh3 meshIn = new DMesh3(sourceMesh); if (is_invalidated()) { return(null); } RemesherPro remesher = new RemesherPro(meshIn); remesher.SetTargetEdgeLength(TargetEdgeLength); remesher.PreventNormalFlips = this.PreventNormalFlips; remesher.EnableFlips = this.EnableFlips; remesher.EnableSplits = this.EnableSplits; remesher.EnableCollapses = this.EnableCollapses; remesher.EnableSmoothing = this.EnableSmoothing; remesher.SmoothSpeedT = this.SmoothingSpeed; TransformedMeshProjectionTarget target = new TransformedMeshProjectionTarget(targetMesh, targetSpatial) { SourceToTargetXForm = source_to_target, TargetToSourceXForm = target_to_source }; remesher.SetProjectionTarget(target); if (sourceMesh.CachedIsClosed == false) { if (remesher.Constraints == null) { remesher.SetExternalConstraints(new MeshConstraints()); } if (BoundaryMode == BoundaryModes.FreeBoundaries) { MeshConstraintUtil.PreserveBoundaryLoops(remesher.Constraints, meshIn); } else if (BoundaryMode == BoundaryModes.FixedBoundaries) { MeshConstraintUtil.FixAllBoundaryEdges(remesher.Constraints, meshIn); } else if (BoundaryMode == BoundaryModes.ConstrainedBoundaries) { MeshConstraintUtil.FixAllBoundaryEdges_AllowSplit(remesher.Constraints, meshIn, 0); } } if (is_invalidated()) { return(null); } remesher.Progress = new ProgressCancel(is_invalidated); remesher.SharpEdgeReprojectionRemesh(RemeshRounds, ProjectionRounds); if (is_invalidated()) { return(null); } return(meshIn); }
public virtual void Update() { if (MeshSource == null) { throw new Exception("PlaneBandExpansionOp: must set valid MeshSource to compute!"); } IMesh imesh = MeshSource.GetIMesh(); if (imesh.HasVertexNormals == false) { throw new Exception("PlaneBandExpansionOp: input mesh does not have surface normals..."); } if (imesh is DMesh3 == false) { throw new Exception("RegionOffsetOp: in current implementation, input mesh must be a DMesh3. Ugh."); } DMesh3 mesh = imesh as DMesh3; IList <int> faces = IndexSource.GetIndices(); // [RMS] this is all f'n ugly! MeshVertexSelection selection = new MeshVertexSelection(mesh); selection.SelectTriangleVertices(faces); // ugly List <Vector2d> seeds = new List <Vector2d>(); foreach (int vid in selection) { foreach (int nbrvid in mesh.VtxVerticesItr(vid)) { if (selection.IsSelected(nbrvid) == false) { seeds.Add(new Vector2d(vid, 0)); break; } } } Func <int, int, float> distanceF = (a, b) => { return((float)mesh.GetVertex(a).Distance(mesh.GetVertex(b))); }; Func <int, bool> nodeF = (vid) => { return(selection.IsSelected(vid)); }; DijkstraGraphDistance dijkstra = new DijkstraGraphDistance(mesh.MaxVertexID, true, nodeF, distanceF, mesh.VtxVerticesItr, seeds); dijkstra.Compute(); float maxDist = dijkstra.MaxDistance; Displacement.Clear(); Displacement.Resize(mesh.MaxVertexID); // todo: can do this in parallel... foreach (int vid in selection) { //Vector3d v = mesh.GetVertex(vid); // [TODO]... double dist = maxDist - dijkstra.GetDistance(vid); double falloff = MathUtil.WyvillFalloff(dist, maxDist * 0.0, maxDist); Vector3d n = mesh.GetVertexNormal(vid); n = n - n.Dot(normal) * normal; n.Normalize(); Displacement[vid] = falloff * offset_distance * n; } // smooth it? result_valid = true; }
public virtual void Update() { base.begin_update(); if (MeshSource == null) { throw new Exception("MeshVertexDisplacementOp: must set valid MeshSource to compute!"); } if (DisplacementSource == null) { throw new Exception("MeshVertexDisplacementOp: must set valid DisplacementSource to compute!"); } DMesh3 meshIn = MeshSource.GetDMeshUnsafe(); IVectorDisplacement displace = DisplacementSource.GetDisplacement(); if (displace.Count != 0 && displace.Count != meshIn.MaxVertexID) { throw new Exception("MeshVertexDisplacementOp: inconsistent counts " + displace.Count.ToString() + " != " + meshIn.MaxVertexID.ToString()); } DMesh3 mesh = new DMesh3(meshIn, MeshHints.None); //if (!mesh.HasVertexNormals) // MeshNormals.QuickCompute(mesh); if (displace.Count > 0) { gParallel.ForEach(mesh.VertexIndices(), (vid) => { Vector3d dv = displace.GetDisplacementForIndex(vid); //Vector3f n = mesh.GetVertexNormal(vid); Vector3d v = mesh.GetVertex(vid); v += dv; mesh.SetVertex(vid, v); }); if (enable_heat_map) { // compute max displace len ColorMap map = new ColorMap(); map.AddPoint(0, Colorf.CornflowerBlue); float d = (float)HeatMapMaxDistance; map.AddPoint(d, Colorf.Orange); map.AddPoint(2 * d, Colorf.VideoYellow); map.AddPoint(4 * d, Colorf.VideoRed); map.AddPoint(-d, Colorf.VideoMagenta); float max_displace = d; gParallel.ForEach(mesh.VertexIndices(), (vid) => { Vector3f dv = (Vector3f)displace.GetDisplacementForIndex(vid); Vector3f n = mesh.GetVertexNormal(vid); float sign = n.Dot(dv) > 0 ? 1 : -1; Colorf c = map.Linear(dv.Length * sign); Colorf existing_c = mesh.GetVertexColor(vid); float preserve__max = max_displace / 2; float t = MathUtil.Clamp(dv.Length / preserve__max, 0.0f, 1.0f); c = (1.0f - t) * existing_c + (t) * c; mesh.SetVertexColor(vid, c); //float t = MathUtil.Clamp(dv.Length / max_displace, -1.0f, 1.0f); //mesh.SetVertexColor(vid, t * Colorf.Orange); }); } } MeshNormals.QuickCompute(mesh); DisplacedMesh = mesh; base.complete_update(); }