public static bool IsSolid(Mesh mesh)
        {
            #if CORK_WRAPPER_CLOCK_DEBUG
            var stopwatch = new Stopwatch();
            stopwatch.Start();
            #endif

            var result = ImportIsSolid(mesh.vertices, mesh.vertices.Length, mesh.triangles, mesh.triangles.Length);

            #if CORK_WRAPPER_CLOCK_DEBUG
            Debug.Log("Mesh IsSolid finished in " + stopwatch.ElapsedMilliseconds + " ms for meshes:\n" +
                      MeshUtils.ShortMeshInfo(mesh));
            #endif
            return(result);
        }
        public bool TryGetValue(int key, out T value)
        {
            MeshUtils.Assert(key < Size, "Key index out of range! " + key + " maxSize: " + Size);

            var item = dictionary[key];

            if (item.valid)
            {
                value = item.data;
                return(true);
            }

            value = default(T);
            return(false);
        }
        public T this[int key]
        {
            get
            {
                MeshUtils.Assert(key < Size, "Key index out of range! " + key + " maxSize: " + Size);
                MeshUtils.Assert(dictionary[key].valid == true, "Key does not exists!");
                return(dictionary[key].data);
            }

            set
            {
                MeshUtils.Assert(dictionary[key].valid == true, "Key does not exists!");
                dictionary[key].data = value;
            }
        }
Exemplo n.º 4
0
Arquivo: Mesh.cs Projeto: 894880010/MP
        /// <summary>
        /// Creates a new edge such that eNew == eOrg.Lnext and eNew.Dst is a newly created vertex.
        /// eOrg and eNew will have the same left face.
        /// </summary>
        public MeshUtils.Edge AddEdgeVertex(MeshUtils.Edge eOrg)
        {
            var eNew    = MeshUtils.MakeEdge(eOrg);
            var eNewSym = eNew._Sym;

            // Connect the new edge appropriately
            MeshUtils.Splice(eNew, eOrg._Lnext);

            // Set vertex and face information
            eNew._Org = eOrg._Dst;
            MeshUtils.MakeVertex(eNewSym, eNew._Org);
            eNew._Lface = eNewSym._Lface = eOrg._Lface;

            return(eNew);
        }
 void Start()
 {
     _meshFilter   = this.GetComponent <MeshFilter>();
     _meshRenderer = this.GetComponent <MeshRenderer>();
     _mesh         = MeshUtils.CreatePlaneMesh(Vector3.zero,
                                               _potentialControlManager.FieldWidth,
                                               _potentialControlManager.FieldHeight,
                                               _fieldSplitNumW, _fieldSplitNumH);
     _meshFilter.sharedMesh = _mesh;
     _meshRenderer.material = _potentialFieldMat;
     _potentialTex          = new Texture2D(_fieldSplitNumW, _fieldSplitNumH,
                                            TextureFormat.RGFloat, false);
     _potentialTex.wrapMode = TextureWrapMode.Clamp;
     _potentialFieldMat.SetTexture("_PotentialFieldTex", _potentialTex);
 }
        public T GetFirstValue()
        {
            for (int i = 0; i < Size; i++)
            {
                var item = dictionary[i];

                if (item.valid)
                {
                    return(item.data);
                }
            }

            MeshUtils.Assert(false, "No valid key!");
            return(default(T));
        }
Exemplo n.º 7
0
    protected virtual void UpdateTexts()
    {
        //float yJump = chart.maxYValue / chart.yDivisions;
        int   fontsize = chart.axisText.GetComponent <TextMesh>().fontSize - chart.yDivisions;
        float xMargin  = 0;

        for (int i = 0; i < YPos.Length; i++)
        {
            String    name = MeshUtils.NameGenerator(objectString, i);
            Transform yt   = YAxis.transform.Find(name);
            yt.localPosition = new Vector3(-AxisWidth * 1.1f, YPos[i]);
            TextMesh mesh = yt.gameObject.GetComponent <TextMesh>();
            mesh.text = chart.YValues[i];
            //mesh.text = (chart.maxYValue - i * yJump).ToString(chart.specifier);
            mesh.color    = axisColor;
            mesh.fontSize = fontsize;
            if (xMargin < mesh.GetComponent <Renderer>().bounds.extents.x)
            {
                xMargin = mesh.GetComponent <Renderer>().bounds.extents.x;
            }
        }
        //print(xMargin);
        chart.margins.x = (xMargin * 2 + AxisWidth + lineWidth) * 1.1f;


        //float xJump = chart.maxXValue / chart.xDivisions;
        //fontsize = chart.axisText.GetComponent<TextMesh>().fontSize - chart.xDivisions;
        float yMargin = 0;

        for (int i = 0; i < XPos.Length; i++)
        {
            String    name = MeshUtils.NameGenerator(objectString, i);
            Transform xt   = XAxis.transform.Find(name);
            xt.localPosition = new Vector3(XPos[i], -AxisWidth * 1.1f);
            TextMesh mesh = xt.gameObject.GetComponent <TextMesh>();
            mesh.text = chart.XValues[i];

            //mesh.text = (chart.maxXValue - i * xJump).ToString(chart.specifier);
            mesh.color    = axisColor;
            mesh.fontSize = fontsize;
            if (yMargin < mesh.GetComponent <Renderer>().bounds.extents.y)
            {
                yMargin = mesh.GetComponent <Renderer>().bounds.extents.y;
            }
        }
        //print(yMargin);
        chart.margins.y = (yMargin * 2 + AxisWidth + lineWidth) * 1.1f;
    }
Exemplo n.º 8
0
    void Awake()
    {
        grid       = MeshUtils.CreatePlane(50f, 50f, 1, 1, new Vector3(0f, -0.001f, 0f));
        grid.layer = LayerMask.NameToLayer("Selection");
        grid.AddComponent <BoxCollider>().center = new Vector3(0f, 0.001f, 0f);
        grid.name = "SelectionBase";
        Destroy(grid.GetComponent <MeshRenderer>());

        selectionData = new float[4] {
            0, 0, 0, 0
        };

        nineSlice = GetComponent <NineSlice>();
        nineSlice.SetSize(unitSize, unitSize);
        nineSlice.transform.rotation = Quaternion.Euler(90f, 0f, 0f);
    }
Exemplo n.º 9
0
    void CreatePlane(string objectName, Vector3 origin, Vector3 horizontalAxis, int resolution)
    {
        var mesh = MeshUtils.GeneratePlane(Vector3.zero, horizontalAxis,
                                           new Vector3(0, Size.y, 0),
                                           resolution,
                                           2,
                                           Vector2.zero,
                                           Vector2.one);

        var go = new GameObject(objectName);

        go.AddComponent <MeshFilter>().sharedMesh = mesh;
        go.AddComponent <MeshRenderer>().material = Material;
        go.transform.SetParent(transform);
        go.transform.localPosition = origin;
    }
Exemplo n.º 10
0
    public static List <Vector2> PredictOutCirCleUVs(IList <Vector2> vectors, float length)
    {
        List <Vector2> ret = new List <Vector2>();

        for (int i = 0; i < vectors.Count; i++)
        {
            Vector3 a = vectors[(i - 1 + vectors.Count) % vectors.Count];
            Vector3 b = vectors[i];
            Vector3 c = vectors[(i + 1) % vectors.Count];

            Vector3 predict = MeshUtils.PredictNormal2D(a, b, c) * length + new Vector3(vectors[i].x, vectors[i].y, 0);

            ret.Add(predict);
        }
        return(ret);
    }
Exemplo n.º 11
0
        /// <summary>
        /// Given three vertices u,v,w such that VertLeq(u,v) .and. VertLeq(v,w),
        /// evaluates the t-coord of the edge uw at the s-coord of the vertex v.
        /// Returns v->t - (uw)(v->s), ie. the signed distance from uw to v.
        /// If uw is vertical (and thus passes thru v), the result is zero.
        /// 
        /// The calculation is extremely accurate and stable, even when v
        /// is very close to u or w.  In particular if we set v->t = 0 and
        /// let r be the negated result (this evaluates (uw)(v->s)), then
        /// r is guaranteed to satisfy MIN(u->t,w->t) less than or equal r less than or equal MAX(u->t,w->t).
        /// </summary>
        public static float EdgeEval(MeshUtils.Vertex u, MeshUtils.Vertex v, MeshUtils.Vertex w)
        {
            Debug.Assert(VertLeq(u, v) && VertLeq(v, w));

            float gapL = v._s - u._s;
            float gapR = w._s - v._s;

            if (gapL + gapR > 0.0f)
            {
                if (gapL < gapR)
                    return (v._t - u._t) + (u._t - w._t)*(gapL/(gapL + gapR));
                return (v._t - w._t) + (w._t - u._t) * (gapR / (gapL + gapR));
            }
            /* vertical line */
            return 0.0f;
        }
Exemplo n.º 12
0
    public static List <int> CreateTrianglesClock(IList <int> indices)
    {
        Debug.Assert(indices.Count % 2 == 0);
        List <int> rets = new List <int>();
        var        n    = indices.Count;

        for (var i = 0; i < n / 2; i++)
        {
            var id1 = indices[i + 0];
            var id2 = indices[i + 1];
            var id3 = indices[n - 1 - (i + 1)];
            var id4 = indices[n - 1 - (i + 0)];
            MeshUtils.AddQuad(rets, id1, id2, id3, id4);
        }
        return(rets);
    }
        protected override void OnCreate()
        {
            base.OnCreate();

            var query = new EntityQueryDesc
            {
                All = new ComponentType[]
                {
                    typeof(SpriteRenderComponent), typeof(LocalToWorld)
                }
            };

            _spriteGroup = GetEntityQuery(query);

            _mesh = MeshUtils.CreateQuad();
        }
Exemplo n.º 14
0
 /* TODO */
 // Game logic
 // Update is called once per frame
 void Update()
 {
     if (Input.GetMouseButtonUp(1) && Input.GetMouseButtonUp(0))
     {
     }
     else if (Input.GetMouseButtonUp(0))
     {
         Vector3 mousePosition = MeshUtils.GetMouseWorldPosition();
         tileArray.SetTileArrayType(mousePosition, TileArrayObject.TileArrayType.Mine);
     }
     else if (Input.GetMouseButtonUp(1))
     {
         Vector3 mousePosition = MeshUtils.GetMouseWorldPosition();
         tileArray.SetFlagStatus(mousePosition);
     }
 }
    private void Start()
    {
        Vector3    meshCenter = MeshUtils.Center(filter.sharedMesh);
        RaycastHit hit;

        if (Physics.Raycast(transform.position + meshCenter, -Vector3.up, out hit))
        {
            transform.position = hit.point - Vector3.up * MeshUtils.MinHeight(filter.sharedMesh);
            transform.RotateAround(transform.position + Vector3.up * MeshUtils.MinHeight(filter.sharedMesh),
                                   Vector3.forward,
                                   hit.transform.eulerAngles.z - transform.eulerAngles.z);
            transform.RotateAround(transform.position + Vector3.up * MeshUtils.MinHeight(filter.sharedMesh),
                                   Vector3.right,
                                   hit.transform.eulerAngles.x - transform.eulerAngles.x);
        }
    }
Exemplo n.º 16
0
        static Mesh <VertexPositionColor> CreateArrow(Matrix44 matrix, Color4 color)
        {
            const float tipHeight  = 0.25f;
            const float tipRadius  = 0.06f;
            const float poleRadius = 0.01f;
            var         tip        = MeshUtils.CreateCone(tipHeight, tipRadius, 20, color);

            TransformMesh(tip, Matrix44.CreateTranslation(0, 1 - tipHeight, 0));
            var pole = MeshUtils.CreateCylinder(1 - tipHeight - 0.1f, poleRadius, 6, color);

            TransformMesh(pole, Matrix44.CreateTranslation(0, 0.1f, 0));
            var arrow = MeshUtils.Combine(tip, pole);

            TransformMesh(arrow, matrix);
            return(arrow);
        }
Exemplo n.º 17
0
        public CustomMaterial(string fileName)
        {
            FileName = fileName;

            if (fileName != "DefaultMaterials")
            {
                try
                {
                    AssetBundle = AssetBundle.LoadFromFile(Path.Combine(Plugin.PluginAssetPath, fileName));

                    GameObject         = AssetBundle.LoadAsset <GameObject>("Assets/_CustomMaterial.prefab");
                    Descriptor         = GameObject.GetComponent <MaterialDescriptor>();
                    MaterialRenderer   = MaterialUtils.GetGameObjectRenderer(GameObject, "pixie");
                    MaterialMeshFilter = MeshUtils.GetGameObjectMeshFilter(GameObject, "pixie");
                }
                catch (Exception ex)
                {
                    Logger.log.Warn($"Something went wrong getting the AssetBundle for '{fileName}'!");
                    Logger.log.Warn(ex);

                    Descriptor = new MaterialDescriptor()
                    {
                        MaterialName = "Invalid Wall (Delete it!)",
                        AuthorName   = fileName,
                        Icon         = Utils.GetErrorIcon()
                    };

                    ErrorMessage = $"File: '{fileName}'" +
                                   "\n\nThis file failed to load." +
                                   "\n\nThis may have been caused by having duplicated files," +
                                   " another wall with the same name already exists or that the custom wall is simply just broken." +
                                   "\n\nThe best thing is probably just to delete it!";

                    FileName = "DefaultMaterials";
                }
            }
            else
            {
                Descriptor = new MaterialDescriptor
                {
                    MaterialName = "Default",
                    AuthorName   = "Beat Saber",
                    Description  = "This is the default walls. (No preview available)",
                    Icon         = Utils.GetDefaultIcon()
                };
            }
        }
Exemplo n.º 18
0
        public override void OnImportAsset(AssetImportContext ctx)
        {
            stage = AnimData.LoadFromFile(ctx.assetPath);
            if (stage == null)
            {
                return;
            }

            MeshUtils.SimplifyStage(stage, Settings.SimplifyFactor);

            savedClips    = new Dictionary <AudioDataPool.AudioPoolKey, AudioClip>();
            totalVertices = 0;
            totalLines    = 0;
            HasFades      = false;
            m_Materials.Clear();

            PreviewTexture = new Texture2D(1, 1);
            PreviewTexture.LoadImage(stage.previewFrames[0], false);
            PreviewTexture.Apply();

            if (Settings.Shader == null || Settings.Shader == "AnimVR/Standard")
            {
                Debug.Log("Resetting shader");
                Settings.Shader = "AnimVR/ImportedLine";
            }

            baseMaterial = new Material(Shader.Find(Settings.Shader));
            baseMaterial.SetFloat("_Unlit", Settings.UnlitByDefault ? 1 : 0);
            baseMaterial.SetFloat("_Gamma", PlayerSettings.colorSpace == ColorSpace.Gamma ? 1.0f : 2.2f);
            baseMaterial.name = Path.GetFileNameWithoutExtension(ctx.assetPath) + "_BaseMaterial";

            needsAudioReimport = false;

            GenerateUnityObject(stage, ctx);

            //var externalObjects = GetExternalObjectMap();

            ctx.AddObjectToAsset(Path.GetFileNameWithoutExtension(ctx.assetPath) + "_BaseMaterial", baseMaterial);

            m_Materials.Add(new SerializableIdentifier(baseMaterial));

            InfoString = "FPS: " + stage.fps + ", " + stage.timelineLength + " frames \n"
                         + totalVertices + " verts, " + totalLines + " lines";

            savedClips = null;
            stage      = null;
        }
Exemplo n.º 19
0
    protected void RemovePlotter(int index)
    {
        string     name = MeshUtils.NameGenerator(Identifier, index);
        GameObject obj  = PlotterGroup.transform.Find(name).gameObject;

        if (obj)
        {
            // Gameobject will not be destroyed until after Update()
            // hence it must detach with parent before Destroy()
            obj.transform.parent = null;
            Destroy(obj);
        }
        else
        {
            Debug.LogError(String.Format("{0} not found?!", name));
        }
    }
Exemplo n.º 20
0
	/*
		Standard Laplacian Smooth Filter
	*/
	public static Vector3[] laplacianFilter(Vector3[] sv, int[] t, bool[] affectedVertices)
	{
		Vector3[] wv = new Vector3[sv.Length];
		List<Vector3> adjacentVertices = new List<Vector3>();

		float dx = 0.0f;
		float dy = 0.0f;
		float dz = 0.0f;

		for (int vi=0; vi< sv.Length; vi++)
		{

			/* Added Condition to only affect needed Vertices */

			if ( !affectedVertices[vi] ) {
				wv [vi] = sv [vi];
				continue;
			}


			// Find the sv neighboring vertices
			adjacentVertices = MeshUtils.findAdjacentNeighbors (sv, t, sv[vi]);

			if (adjacentVertices.Count != 0)
			{
				dx = 0.0f;
				dy = 0.0f;
				dz = 0.0f;

				//Debug.Log("Vertex Index Length = "+vertexIndexes.Length);
				// Add the vertices and divide by the number of vertices
				for (int j=0; j<adjacentVertices.Count; j++)
				{
					dx += adjacentVertices[j].x;
					dy += adjacentVertices[j].y;
					dz += adjacentVertices[j].z;
				}

				wv[vi].x = dx / adjacentVertices.Count;
				wv[vi].y = dy / adjacentVertices.Count;
				wv[vi].z = dz / adjacentVertices.Count;
			}
		}

		return wv;
	}
Exemplo n.º 21
0
 // Token: 0x06004179 RID: 16761 RVA: 0x0014AA50 File Offset: 0x00148E50
 public void Invert()
 {
     foreach (CSGPolygon csgpolygon in this.Polygons)
     {
         csgpolygon.Flip();
     }
     this.Plane.Flip();
     if (this.FrontChild != null)
     {
         this.FrontChild.Invert();
     }
     if (this.BackChild != null)
     {
         this.BackChild.Invert();
     }
     MeshUtils.Swap <CSGNode>(ref this.FrontChild, ref this.BackChild);
 }
Exemplo n.º 22
0
        // Token: 0x060041CA RID: 16842 RVA: 0x0014E178 File Offset: 0x0014C578
        public GameObject Duplicate(bool duplicateMaterials)
        {
            GameObject gameObject  = UnityEngine.Object.Instantiate <GameObject>(base.gameObject);
            Mesh       sharedMesh  = base.GetComponent <MeshFilter>().sharedMesh;
            Mesh       sharedMesh2 = MeshUtils.CopyMesh(sharedMesh);

            gameObject.GetComponent <MeshFilter>().sharedMesh = sharedMesh2;
            if (duplicateMaterials)
            {
                MeshRenderer component = gameObject.GetComponent <MeshRenderer>();
                if (component && component.sharedMaterials.Length > 0)
                {
                    component.sharedMaterials = MeshUtils.CopyMaterials(component.sharedMaterials);
                }
            }
            return(gameObject);
        }
Exemplo n.º 23
0
    public void Start()
    {
        Application.RegisterLogCallback(HandleLog);

        MeshUtils.InitStaticValues();
        CubeWorldPlayerPreferences.LoadPreferences();
        PreferencesUpdated();

        State    = state = GameManagerUnityState.MAIN_MENU;
        mainMenu = new MainMenu(this);

        sectorManagerUnity  = new SectorManagerUnity(this);
        objectsManagerUnity = new CWObjectsManagerUnity(this);
        fxManagerUnity      = new CWFxManagerUnity(this);

        worldManagerUnity = new WorldManagerUnity(this);
    }
Exemplo n.º 24
0
    // Update is called once per frame
    void Update()
    {
        Vector3 arrowPosBr = flecheBr.localPosition;
        Vector3 arrowPosTr = flecheTr.localPosition;

        if (arrowPosBr.x == lastArrowPosBr.x && arrowPosTr.x == lastArrowPosTr.x)
        {
            return;
        }

        mf.mesh = MeshUtils.CreateCone(2f, flecheBr.GetComponent <MeshRenderer>().bounds.center.x - flecheBr.GetComponent <MeshRenderer>().bounds.extents.x - transform.position.x, transform.position.x - flecheTr.GetComponent <MeshRenderer>().bounds.center.x - flecheTr.GetComponent <MeshRenderer>().bounds.extents.x, 18);

        mc.sharedMesh = mesh;
        //mat.mainTexture = mainTex;
        lastArrowPosTr = arrowPosTr;
        lastArrowPosBr = arrowPosBr;
    }
Exemplo n.º 25
0
    public void UpdateMesh()
    {
        // GetRearrangedData make the latest sampling as the last point of the Line chart.
        // Prepare the input for making the mesh of the each Line.
        Vector3[] lines = CreateLineFromData(GetRearrangedData());

        // Generate Line Mesh in the DataSeries which contain a mesh Renderer.
        UpdateMesh(MeshUtils.GenerateLineMesh(lines, timeChart.lineWidth));

        // TODO: A method that pre-arrange yPos of floating values so that
        //       it won't be overlapping (when there are several Lines)

        // Update the floating value tracing the last sampling of the each Line.
        // GetRearrangedData() begins with the lastest sampling.
        //UpdateFloatingValue(lines[0]);
        UpdateFloatingValue(lines, timeChart.TimeSliderPosition);
    }
Exemplo n.º 26
0
        /// <summary>
        /// Flip normals to opposite direction
        /// </summary>
        public void FlipNormals()
        {
            if (generationMode == 1)
            {
                return;
            }

            flipNormals = !flipNormals;

            var mesh = GetComponent <MeshFilter>().sharedMesh;

            // reverse normals
            MeshUtils.ReverseNormals(mesh);

            // recalculate tangents
            MeshUtils.CalculateTangents(mesh);
        }
Exemplo n.º 27
0
 private void InitVT()
 {
     ResetVUT();
     if (_strokeType == StrokeType.Point)
     {
         CalCircleMeshData(SemiCircleSegment * 2);
     }
     else
     {
         _verticesCurve = MeshUtils.GetVertices(_curvePoints, _width * 0.5f);
         if (!_isClose)
         {
             AddSectorMeshData();
         }
         UpdatePercent(1);
     }
 }
Exemplo n.º 28
0
    void UpdateQuad()
    {
        float desired_ratio = 1.0f;

        if (sprite_sheet != null)
        {
            desired_ratio = (float)(sprite_sheet.height / sprite_count_y) / (float)(sprite_sheet.width / sprite_count_x);
        }
        if (float.IsInfinity(desired_ratio))
        {
            desired_ratio = 1.0f;
        }
        MeshFilter mf = GetComponent <MeshFilter>();

        DestroyImmediate(mf.sharedMesh);
        mf.sharedMesh = MeshUtils.MakeQuad(desired_height, desired_ratio);
    }
Exemplo n.º 29
0
    /// <summary>
    /// Splice is the basic operation for changing the
    /// mesh connectivity and topology.  It changes the mesh so that
    ///     eOrg->Onext = OLD( eDst->Onext )
    ///     eDst->Onext = OLD( eOrg->Onext )
    /// where OLD(...) means the value before the meshSplice operation.
    ///
    /// This can have two effects on the vertex structure:
    ///  - if eOrg->Org != eDst->Org, the two vertices are merged together
    ///  - if eOrg->Org == eDst->Org, the origin is split into two vertices
    /// In both cases, eDst->Org is changed and eOrg->Org is untouched.
    ///
    /// Similarly (and independently) for the face structure,
    ///  - if eOrg->Lface == eDst->Lface, one loop is split into two
    ///  - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one
    /// In both cases, eDst->Lface is changed and eOrg->Lface is unaffected.
    ///
    /// Some special cases:
    /// If eDst == eOrg, the operation has no effect.
    /// If eDst == eOrg->Lnext, the new face will have a single edge.
    /// If eDst == eOrg->Lprev, the old face will have a single edge.
    /// If eDst == eOrg->Onext, the new vertex will have a single edge.
    /// If eDst == eOrg->Oprev, the old vertex will have a single edge.
    /// </summary>
    public static void Splice(IPool pool, MeshUtils.Edge eOrg, MeshUtils.Edge eDst)
    {
        if (eOrg == eDst)
        {
            return;
        }

        bool joiningVertices = false;

        if (eDst._Org != eOrg._Org)
        {
            // We are merging two disjoint vertices -- destroy eDst->Org
            joiningVertices = true;
            MeshUtils.KillVertex(pool, eDst._Org, eOrg._Org);
        }
        bool joiningLoops = false;

        if (eDst._Lface != eOrg._Lface)
        {
            // We are connecting two disjoint loops -- destroy eDst->Lface
            joiningLoops = true;
            MeshUtils.KillFace(pool, eDst._Lface, eOrg._Lface);
        }

        // Change the edge structure
        MeshUtils.Splice(eDst, eOrg);

        switch (joiningVertices)
        {
        case false:
            // We split one vertex into two -- the new vertex is eDst->Org.
            // Make sure the old vertex points to a valid half-edge.
            MeshUtils.MakeVertex(pool, eDst, eOrg._Org);
            eOrg._Org._anEdge = eOrg;
            break;
        }
        switch (joiningLoops)
        {
        case false:
            // We split one loop into two -- the new loop is eDst->Lface.
            // Make sure the old face points to a valid half-edge.
            MeshUtils.MakeFace(pool, eDst, eOrg._Lface);
            eOrg._Lface._anEdge = eOrg;
            break;
        }
    }
Exemplo n.º 30
0
        private static void Postfix(ref ObstacleController __instance, StretchableObstacle ____stretchableObstacle, ref SimpleColorSO ____color)
        {
            try
            {
                CustomMaterial customMaterial = MaterialAssetLoader.CustomMaterialObjects[MaterialAssetLoader.SelectedMaterial];
                if (customMaterial.FileName != "DefaultMaterials")
                {
                    Renderer mesh  = __instance.gameObject.GetComponentInChildren <Renderer>();
                    Color    color = ____color.color;

                    if (customMaterial.Descriptor.Overlay)
                    {
                        GameObject overlay = MeshUtils.CreateOverlay(mesh, customMaterial.MaterialRenderer, customMaterial.Descriptor.OverlayOffset);
                        MaterialUtils.SetMaterialsColor(overlay?.GetComponent <Renderer>().materials, color);
                        if (customMaterial.Descriptor.ReplaceMesh)
                        {
                            MeshUtils.ReplaceMesh(overlay.GetComponent <MeshFilter>(), customMaterial.MaterialMeshFilter, customMaterial.Descriptor.MeshScaleMultiplier);
                            if (!customMaterial.Descriptor.ReplaceOnlyOverlayMesh)
                            {
                                MeshUtils.ReplaceMesh(__instance.gameObject.GetComponentInChildren <MeshFilter>(), customMaterial.MaterialMeshFilter, customMaterial.Descriptor.MeshScaleMultiplier);
                            }
                        }
                    }
                    else
                    {
                        MaterialUtils.ReplaceRenderer(mesh, customMaterial.MaterialRenderer);
                        MaterialUtils.SetMaterialsColor(mesh?.materials, color);
                        if (customMaterial.Descriptor.ReplaceMesh)
                        {
                            MeshUtils.ReplaceMesh(__instance.gameObject.GetComponentInChildren <MeshFilter>(), customMaterial.MaterialMeshFilter, customMaterial.Descriptor.MeshScaleMultiplier);
                        }
                    }
                }

                if (!Configuration.EnableObstacleFrame)
                {
                    ParametricBoxFrameController frame = ____stretchableObstacle.GetPrivateField <ParametricBoxFrameController>("_obstacleFrame");
                    frame.enabled = false;
                }
            }
            catch (Exception ex)
            {
                Logger.log.Error(ex);
            }
        }
Exemplo n.º 31
0
        /// <summary>
        /// Splits eOrg into two edges eOrg and eNew such that eNew == eOrg.Lnext.
        /// The new vertex is eOrg.Dst == eNew.Org.
        /// eOrg and eNew will have the same left face.
        /// </summary>
        public MeshUtils.Edge SplitEdge(IPool pool, MeshUtils.Edge eOrg)
        {
            var eTmp = AddEdgeVertex(pool, eOrg);
            var eNew = eTmp._Sym;

            // Disconnect eOrg from eOrg->Dst and connect it to eNew->Org
            MeshUtils.Splice(eOrg._Sym, eOrg._Sym._Oprev);
            MeshUtils.Splice(eOrg._Sym, eNew);

            // Set the vertex and face information
            eOrg._Dst          = eNew._Org;
            eNew._Dst._anEdge  = eNew._Sym;     // may have pointed to eOrg->Sym
            eNew._Rface        = eOrg._Rface;
            eNew._winding      = eOrg._winding; // copy old winding information
            eNew._Sym._winding = eOrg._Sym._winding;

            return(eNew);
        }
Exemplo n.º 32
0
 public static bool VertCCW(MeshUtils.Vertex u, MeshUtils.Vertex v, MeshUtils.Vertex w)
 {
     return (u._s * (v._t - w._t) + v._s * (w._t - u._t) + w._s * (u._t - v._t)) >= 0.0f;
 }
Exemplo n.º 33
0
        /// <summary>
        /// Add a new active region to the sweep line, *somewhere* below "regAbove"
        /// (according to where the new edge belongs in the sweep-line dictionary).
        /// The upper edge of the new region will be "eNewUp".
        /// Winding number and "inside" flag are not updated.
        /// </summary>
        private ActiveRegion AddRegionBelow(ActiveRegion regAbove, MeshUtils.Edge eNewUp)
        {
            var regNew = new ActiveRegion();

            regNew._eUp = eNewUp;
            regNew._nodeUp = _dict.InsertBefore(regAbove._nodeUp, regNew);
            regNew._fixUpperEdge = false;
            regNew._sentinel = false;
            regNew._dirty = false;

            eNewUp._activeRegion = regNew;

            return regNew;
        }
Exemplo n.º 34
0
 public static float VertL1Dist(MeshUtils.Vertex u, MeshUtils.Vertex v)
 {
     return Math.Abs(u._s - v._s) + Math.Abs(u._t - v._t);
 }
Exemplo n.º 35
0
        /// <summary>
        /// The event vertex lies exacty on an already-processed edge or vertex.
        /// Adding the new vertex involves splicing it into the already-processed
        /// part of the mesh.
        /// </summary>
        private void ConnectLeftDegenerate(ActiveRegion regUp, MeshUtils.Vertex vEvent)
        {
            var e = regUp._eUp;
            if (Geom.VertEq(e._Org, vEvent))
            {
                // e.Org is an unprocessed vertex - just combine them, and wait
                // for e.Org to be pulled from the queue
                // C# : in the C version, there is a flag but it was never implemented
                // the vertices are before beginning the tesselation
                throw new InvalidOperationException("Vertices should have been merged before");
            }

            if (!Geom.VertEq(e._Dst, vEvent))
            {
                // General case -- splice vEvent into edge e which passes through it
                _mesh.SplitEdge(e._Sym);
                if (regUp._fixUpperEdge)
                {
                    // This edge was fixable -- delete unused portion of original edge
                    _mesh.Delete(e._Onext);
                    regUp._fixUpperEdge = false;
                }
                _mesh.Splice(vEvent._anEdge, e);
                SweepEvent(vEvent);	// recurse
                return;
            }

            // See above
            throw new InvalidOperationException("Vertices should have been merged before");
        }
Exemplo n.º 36
0
        /// <summary>
        /// Find some weights which describe how the intersection vertex is
        /// a linear combination of "org" and "dest".  Each of the two edges
        /// which generated "isect" is allocated 50% of the weight; each edge
        /// splits the weight between its org and dst according to the
        /// relative distance to "isect".
        /// </summary>
        private void VertexWeights(MeshUtils.Vertex isect, MeshUtils.Vertex org, MeshUtils.Vertex dst, out float w0, out float w1)
        {
            var t1 = Geom.VertL1Dist(org, isect);
            var t2 = Geom.VertL1Dist(dst, isect);

            w0 = 0.5f * t2 / (t1 + t2);
            w1 = 0.5f * t1 / (t1 + t2);

            isect._coords.X += w0 * org._coords.X + w1 * dst._coords.X;
            isect._coords.Y += w0 * org._coords.Y + w1 * dst._coords.Y;
            isect._coords.Z += w0 * org._coords.Z + w1 * dst._coords.Z;
        }
Exemplo n.º 37
0
        /// <summary>
        /// Purpose: connect a "right" vertex vEvent (one where all edges go left)
        /// to the unprocessed portion of the mesh.  Since there are no right-going
        /// edges, two regions (one above vEvent and one below) are being merged
        /// into one.  "regUp" is the upper of these two regions.
        /// 
        /// There are two reasons for doing this (adding a right-going edge):
        ///  - if the two regions being merged are "inside", we must add an edge
        ///    to keep them separated (the combined region would not be monotone).
        ///  - in any case, we must leave some record of vEvent in the dictionary,
        ///    so that we can merge vEvent with features that we have not seen yet.
        ///    For example, maybe there is a vertical edge which passes just to
        ///    the right of vEvent; we would like to splice vEvent into this edge.
        /// 
        /// However, we don't want to connect vEvent to just any vertex.  We don''t
        /// want the new edge to cross any other edges; otherwise we will create
        /// intersection vertices even when the input data had no self-intersections.
        /// (This is a bad thing; if the user's input data has no intersections,
        /// we don't want to generate any false intersections ourselves.)
        /// 
        /// Our eventual goal is to connect vEvent to the leftmost unprocessed
        /// vertex of the combined region (the union of regUp and regLo).
        /// But because of unseen vertices with all right-going edges, and also
        /// new vertices which may be created by edge intersections, we don''t
        /// know where that leftmost unprocessed vertex is.  In the meantime, we
        /// connect vEvent to the closest vertex of either chain, and mark the region
        /// as "fixUpperEdge".  This flag says to delete and reconnect this edge
        /// to the next processed vertex on the boundary of the combined region.
        /// Quite possibly the vertex we connected to will turn out to be the
        /// closest one, in which case we won''t need to make any changes.
        /// </summary>
        private void ConnectRightVertex(ActiveRegion regUp, MeshUtils.Edge eBottomLeft)
        {
            var eTopLeft = eBottomLeft._Onext;
            var regLo = RegionBelow(regUp);
            var eUp = regUp._eUp;
            var eLo = regLo._eUp;
            bool degenerate = false;

            if (eUp._Dst != eLo._Dst)
            {
                CheckForIntersect(regUp);
            }

            // Possible new degeneracies: upper or lower edge of regUp may pass
            // through vEvent, or may coincide with new intersection vertex
            if (Geom.VertEq(eUp._Org, _event))
            {
                _mesh.Splice(eTopLeft._Oprev, eUp);
                regUp = TopLeftRegion(regUp);
                eTopLeft = RegionBelow(regUp)._eUp;
                FinishLeftRegions(RegionBelow(regUp), regLo);
                degenerate = true;
            }
            if (Geom.VertEq(eLo._Org, _event))
            {
                _mesh.Splice(eBottomLeft, eLo._Oprev);
                eBottomLeft = FinishLeftRegions(regLo, null);
                degenerate = true;
            }
            if (degenerate)
            {
                AddRightEdges(regUp, eBottomLeft._Onext, eTopLeft, eTopLeft, true);
                return;
            }

            // Non-degenerate situation -- need to add a temporary, fixable edge.
            // Connect to the closer of eLo.Org, eUp.Org.
            MeshUtils.Edge eNew;
            if (Geom.VertLeq(eLo._Org, eUp._Org))
            {
                eNew = eLo._Oprev;
            }
            else
            {
                eNew = eUp;
            }
            eNew = _mesh.Connect(eBottomLeft._Lprev, eNew);

            // Prevent cleanup, otherwise eNew might disappear before we've even
            // had a chance to mark it as a temporary edge.
            AddRightEdges(regUp, eNew, eNew._Onext, eNew._Onext, false);
            eNew._Sym._activeRegion._fixUpperEdge = true;
            WalkDirtyRegions(regUp);
        }
Exemplo n.º 38
0
        /// <summary>
        /// Given three vertices u,v,w such that VertLeq(u,v) && VertLeq(v,w),
        /// evaluates the t-coord of the edge uw at the s-coord of the vertex v.
        /// Returns v->t - (uw)(v->s), ie. the signed distance from uw to v.
        /// If uw is vertical (and thus passes thru v), the result is zero.
        /// 
        /// The calculation is extremely accurate and stable, even when v
        /// is very close to u or w.  In particular if we set v->t = 0 and
        /// let r be the negated result (this evaluates (uw)(v->s)), then
        /// r is guaranteed to satisfy MIN(u->t,w->t) <= r <= MAX(u->t,w->t).
        /// </summary>
        public static Real EdgeEval(MeshUtils.Vertex u, MeshUtils.Vertex v, MeshUtils.Vertex w)
        {
            Debug.Assert(VertLeq(u, v) && VertLeq(v, w));

            var gapL = v._s - u._s;
            var gapR = w._s - v._s;

            if (gapL + gapR > 0.0f)
            {
                if (gapL < gapR)
                {
                    return (v._t - u._t) + (u._t - w._t) * (gapL / (gapL + gapR));
                }
                else
                {
                    return (v._t - w._t) + (w._t - u._t) * (gapR / (gapL + gapR));
                }
            }
            /* vertical line */
            return 0;
        }
Exemplo n.º 39
0
        public static Real TransSign(MeshUtils.Vertex u, MeshUtils.Vertex v, MeshUtils.Vertex w)
        {
            Debug.Assert(TransLeq(u, v) && TransLeq(v, w));

            var gapL = v._t - u._t;
            var gapR = w._t - v._t;

            if (gapL + gapR > 0.0f)
            {
                return (v._s - w._s) * gapL + (v._s - u._s) * gapR;
            }
            /* vertical line */
            return 0;
        }
Exemplo n.º 40
0
 public static bool TransLeq(MeshUtils.Vertex lhs, MeshUtils.Vertex rhs)
 {
     return (lhs._t < rhs._t) || (lhs._t == rhs._t && lhs._s <= rhs._s);
 }
Exemplo n.º 41
0
        /// <summary>
        /// Returns a number whose sign matches EdgeEval(u,v,w) but which
        /// is cheaper to evaluate. Returns > 0, == 0 , or < 0
        /// as v is above, on, or below the edge uw.
        /// </summary>
        public static Real EdgeSign(MeshUtils.Vertex u, MeshUtils.Vertex v, MeshUtils.Vertex w)
        {
            Debug.Assert(VertLeq(u, v) && VertLeq(v, w));

            var gapL = v._s - u._s;
            var gapR = w._s - v._s;

            if (gapL + gapR > 0.0f)
            {
                return (v._t - w._t) * gapL + (v._t - u._t) * gapR;
            }
            /* vertical line */
            return 0;
        }
    // Use this for initialization
    void Start()
    {
        GameObject editorQuad = GameObject.Find ("EditorQuad");

        meshUtils = new MeshUtils ();
        mesh = editorQuad.GetComponent<MeshFilter>().mesh;

        selectionQuad = GameObject.Find("SelectionQuad");

        // Initalize the size of the render texture
        RenderTexture rt = editorQuad.GetComponent<Renderer> ().material.mainTexture as RenderTexture;
        int resolution = (int)Mathf.Max (Screen.width, Screen.height) * 2;
        rt.width = resolution;
        rt.height = resolution;

        Init ();
    }
Exemplo n.º 43
0
        /// <summary>
        /// Find some weights which describe how the intersection vertex is
        /// a linear combination of "org" and "dest".  Each of the two edges
        /// which generated "isect" is allocated 50% of the weight; each edge
        /// splits the weight between its org and dst according to the
        /// relative distance to "isect".
        /// </summary>
        private void VertexWeights(MeshUtils.Vertex isect, MeshUtils.Vertex org, MeshUtils.Vertex dst, out Real w0, out Real w1)
        {
            var t1 = Geom.VertL1dist(org, isect);
            var t2 = Geom.VertL1dist(dst, isect);

            w0 = (t2 / (t1 + t2)) / 2.0f;
            w1 = (t1 / (t1 + t2)) / 2.0f;

            isect._coords.X += w0 * org._coords.X + w1 * dst._coords.X;
            isect._coords.Y += w0 * org._coords.Y + w1 * dst._coords.Y;
            isect._coords.Z += w0 * org._coords.Z + w1 * dst._coords.Z;
        }
Exemplo n.º 44
0
 /// <summary>
 /// Two vertices with idential coordinates are combined into one.
 /// e1.Org is kept, while e2.Org is discarded.
 /// </summary>
 private void SpliceMergeVertices(MeshUtils.Edge e1, MeshUtils.Edge e2)
 {
     _mesh.Splice(e1, e2);
 }
Exemplo n.º 45
0
 /// <summary>
 /// Replace an upper edge which needs fixing (see ConnectRightVertex).
 /// </summary>
 private void FixUpperEdge(ActiveRegion reg, MeshUtils.Edge newEdge)
 {
     Debug.Assert(reg._fixUpperEdge);
     _mesh.Delete(reg._eUp);
     reg._fixUpperEdge = false;
     reg._eUp = newEdge;
     newEdge._activeRegion = reg;
 }
Exemplo n.º 46
0
 public static bool VertEq(MeshUtils.Vertex lhs, MeshUtils.Vertex rhs)
 {
     return lhs._s == rhs._s && lhs._t == rhs._t;
 }
Exemplo n.º 47
0
 public static bool VertLeq(MeshUtils.Vertex lhs, MeshUtils.Vertex rhs)
 {
     return (lhs._s < rhs._s) || (lhs._s == rhs._s && lhs._t <= rhs._t);
 }
Exemplo n.º 48
0
 public static bool EdgeGoesLeft(MeshUtils.Edge e)
 {
     return VertLeq(e._Dst, e._Org);
 }
Exemplo n.º 49
0
        /// <summary>
        /// TessellateMonoRegion( face ) tessellates a monotone region
        /// (what else would it do??)  The region must consist of a single
        /// loop of half-edges (see mesh.h) oriented CCW.  "Monotone" in this
        /// case means that any vertical line intersects the interior of the
        /// region in a single interval.  
        /// 
        /// Tessellation consists of adding interior edges (actually pairs of
        /// half-edges), to split the region into non-overlapping triangles.
        /// 
        /// The basic idea is explained in Preparata and Shamos (which I don't
        /// have handy right now), although their implementation is more
        /// complicated than this one.  The are two edge chains, an upper chain
        /// and a lower chain.  We process all vertices from both chains in order,
        /// from right to left.
        /// 
        /// The algorithm ensures that the following invariant holds after each
        /// vertex is processed: the untessellated region consists of two
        /// chains, where one chain (say the upper) is a single edge, and
        /// the other chain is concave.  The left vertex of the single edge
        /// is always to the left of all vertices in the concave chain.
        /// 
        /// Each step consists of adding the rightmost unprocessed vertex to one
        /// of the two chains, and forming a fan of triangles from the rightmost
        /// of two chain endpoints.  Determining whether we can add each triangle
        /// to the fan is a simple orientation test.  By making the fan as large
        /// as possible, we restore the invariant (check it yourself).
        /// </summary>
        private void TessellateMonoRegion(MeshUtils.Face face)
        {
            // All edges are oriented CCW around the boundary of the region.
            // First, find the half-edge whose origin vertex is rightmost.
            // Since the sweep goes from left to right, face->anEdge should
            // be close to the edge we want.
            var up = face._anEdge;
            Debug.Assert(up._Lnext != up && up._Lnext._Lnext != up);

            for (; Geom.VertLeq(up.Dst, up._Org); up = up.Lprev)
            {
            }
            for (; Geom.VertLeq(up._Org, up.Dst); up = up._Lnext)
            {
            }

            var lo = up.Lprev;

            while (up._Lnext != lo)
            {
                if (Geom.VertLeq(up.Dst, lo._Org))
                {
                    // up.Dst is on the left. It is safe to form triangles from lo.Org.
                    // The EdgeGoesLeft test guarantees progress even when some triangles
                    // are CW, given that the upper and lower chains are truly monotone.
                    while (lo._Lnext != up && (Geom.EdgeGoesLeft(lo._Lnext)
                        || Geom.EdgeSign(lo._Org, lo.Dst, lo._Lnext.Dst) <= 0.0f))
                    {
                        lo = _mesh.Connect(lo._Lnext, lo)._Sym;
                    }
                    lo = lo.Lprev;
                }
                else
                {
                    // lo.Org is on the left.  We can make CCW triangles from up.Dst.
                    while (lo._Lnext != up && (Geom.EdgeGoesRight(up.Lprev)
                        || Geom.EdgeSign(up.Dst, up._Org, up.Lprev._Org) >= 0.0f))
                    {
                        up = _mesh.Connect(up, up.Lprev)._Sym;
                    }
                    up = up._Lnext;
                }
            }

            // Now lo.Org == up.Dst == the leftmost vertex.  The remaining region
            // can be tessellated in a fan from this leftmost vertex.
            Debug.Assert(lo._Lnext != up);
            while (lo._Lnext._Lnext != up)
            {
                lo = _mesh.Connect(lo._Lnext, lo)._Sym;
            }
        }
Exemplo n.º 50
0
        /// <summary>
        /// We've computed a new intersection point, now we need a "data" pointer
        /// from the user so that we can refer to this new vertex in the
        /// rendering callbacks.
        /// </summary>
        private void GetIntersectData(MeshUtils.Vertex isect, MeshUtils.Vertex orgUp, MeshUtils.Vertex dstUp, MeshUtils.Vertex orgLo, MeshUtils.Vertex dstLo)
        {
            isect._coords = Vec3.Zero;
            Real w0, w1, w2, w3;
            VertexWeights(isect, orgUp, dstUp, out w0, out w1);
            VertexWeights(isect, orgLo, dstLo, out w2, out w3);

            if (_combineCallback != null)
            {
                isect._data = _combineCallback(
                    isect._coords,
                    new object[] { orgUp._data, dstUp._data, orgLo._data, dstLo._data },
                    new Real[] { w0, w1, w2, w3 }
                );
            }
        }
Exemplo n.º 51
0
 private int GetNeighbourFace(MeshUtils.Edge edge)
 {
     if (edge.Rface == null)
         return MeshUtils.Undef;
     if (!edge.Rface._inside)
         return MeshUtils.Undef;
     return edge.Rface._n;
 }
Exemplo n.º 52
0
        /// <summary>
        /// Does everything necessary when the sweep line crosses a vertex.
        /// Updates the mesh and the edge dictionary.
        /// </summary>
        private void SweepEvent(MeshUtils.Vertex vEvent)
        {
            _event = vEvent;

            // Check if this vertex is the right endpoint of an edge that is
            // already in the dictionary. In this case we don't need to waste
            // time searching for the location to insert new edges.
            var e = vEvent._anEdge;
            while (e._activeRegion == null)
            {
                e = e._Onext;
                if (e == vEvent._anEdge)
                {
                    // All edges go right -- not incident to any processed edges
                    ConnectLeftVertex(vEvent);
                    return;
                }
            }

            // Processing consists of two phases: first we "finish" all the
            // active regions where both the upper and lower edges terminate
            // at vEvent (ie. vEvent is closing off these regions).
            // We mark these faces "inside" or "outside" the polygon according
            // to their winding number, and delete the edges from the dictionary.
            // This takes care of all the left-going edges from vEvent.
            var regUp = TopLeftRegion(e._activeRegion);
            var reg = RegionBelow(regUp);
            var eTopLeft = reg._eUp;
            var eBottomLeft = FinishLeftRegions(reg, null);

            // Next we process all the right-going edges from vEvent. This
            // involves adding the edges to the dictionary, and creating the
            // associated "active regions" which record information about the
            // regions between adjacent dictionary edges.
            if (eBottomLeft._Onext == eTopLeft)
            {
                // No right-going edges -- add a temporary "fixable" edge
                ConnectRightVertex(regUp, eBottomLeft);
            }
            else
            {
                AddRightEdges(regUp, eBottomLeft._Onext, eTopLeft, eTopLeft, true);
            }
        }
Exemplo n.º 53
0
 public static bool VertLeq(MeshUtils.Vertex lhs, MeshUtils.Vertex rhs)
 {
     // ReSharper disable CompareOfFloatsByEqualityOperator
     return (lhs._s < rhs._s) || (lhs._s == rhs._s && lhs._t <= rhs._t);
     // ReSharper restore CompareOfFloatsByEqualityOperator
 }
Exemplo n.º 54
0
 public static void AddWinding(MeshUtils.Edge eDst, MeshUtils.Edge eSrc)
 {
     eDst._winding += eSrc._winding;
     eDst._Sym._winding += eSrc._Sym._winding;
 }
Exemplo n.º 55
0
 static void Swap(ref MeshUtils.Vertex a, ref MeshUtils.Vertex b)
 {
     var tmp = a;
     a = b;
     b = tmp;
 }
Exemplo n.º 56
0
        /// <summary>
        /// Given edges (o1,d1) and (o2,d2), compute their point of intersection.
        /// The computed point is guaranteed to lie in the intersection of the
        /// bounding rectangles defined by each edge.
        /// </summary>
        public static void EdgeIntersect(MeshUtils.Vertex o1, MeshUtils.Vertex d1, MeshUtils.Vertex o2, MeshUtils.Vertex d2, MeshUtils.Vertex v)
        {
            // This is certainly not the most efficient way to find the intersection
            // of two line segments, but it is very numerically stable.
            // 
            // Strategy: find the two middle vertices in the VertLeq ordering,
            // and interpolate the intersection s-value from these.  Then repeat
            // using the TransLeq ordering to find the intersection t-value.

            if (!VertLeq(o1, d1)) { Swap(ref o1, ref d1); }
            if (!VertLeq(o2, d2)) { Swap(ref o2, ref d2); }
            if (!VertLeq(o1, o2)) { Swap(ref o1, ref o2); Swap(ref d1, ref d2); }

            if (!VertLeq(o2, d1))
            {
                // Technically, no intersection -- do our best
                v._s = (o2._s + d1._s) / 2.0f;
            }
            else if (VertLeq(d1, d2))
            {
                // Interpolate between o2 and d1
                var z1 = EdgeEval(o1, o2, d1);
                var z2 = EdgeEval(o2, d1, d2);
                if (z1 + z2 < 0.0f)
                {
                    z1 = -z1;
                    z2 = -z2;
                }
                v._s = Interpolate(z1, o2._s, z2, d1._s);
            }
            else
            {
                // Interpolate between o2 and d2
                var z1 = EdgeSign(o1, o2, d1);
                var z2 = -EdgeSign(o1, d2, d1);
                if (z1 + z2 < 0.0f)
                {
                    z1 = -z1;
                    z2 = -z2;
                }
                v._s = Interpolate(z1, o2._s, z2, d2._s);
            }

            // Now repeat the process for t

            if (!TransLeq(o1, d1)) { Swap(ref o1, ref d1); }
            if (!TransLeq(o2, d2)) { Swap(ref o2, ref d2); }
            if (!TransLeq(o1, o2)) { Swap(ref o1, ref o2); Swap(ref d1, ref d2); }

            if (!TransLeq(o2, d1))
            {
                // Technically, no intersection -- do our best
                v._t = (o2._t + d1._t) / 2.0f;
            }
            else if (TransLeq(d1, d2))
            {
                // Interpolate between o2 and d1
                var z1 = TransEval(o1, o2, d1);
                var z2 = TransEval(o2, d1, d2);
                if (z1 + z2 < 0.0f)
                {
                    z1 = -z1;
                    z2 = -z2;
                }
                v._t = Interpolate(z1, o2._t, z2, d1._t);
            }
            else
            {
                // Interpolate between o2 and d2
                var z1 = TransSign(o1, o2, d1);
                var z2 = -TransSign(o1, d2, d1);
                if (z1 + z2 < 0.0f)
                {
                    z1 = -z1;
                    z2 = -z2;
                }
                v._t = Interpolate(z1, o2._t, z2, d2._t);
            }
        }
Exemplo n.º 57
0
 public static bool EdgeGoesRight(MeshUtils.Edge e)
 {
     return VertLeq(e._Org, e._Dst);
 }
Exemplo n.º 58
0
        /// <summary>
        /// Purpose: insert right-going edges into the edge dictionary, and update
        /// winding numbers and mesh connectivity appropriately.  All right-going
        /// edges share a common origin vOrg.  Edges are inserted CCW starting at
        /// eFirst; the last edge inserted is eLast.Oprev.  If vOrg has any
        /// left-going edges already processed, then eTopLeft must be the edge
        /// such that an imaginary upward vertical segment from vOrg would be
        /// contained between eTopLeft.Oprev and eTopLeft; otherwise eTopLeft
        /// should be null.
        /// </summary>
        private void AddRightEdges(ActiveRegion regUp, MeshUtils.Edge eFirst, MeshUtils.Edge eLast, MeshUtils.Edge eTopLeft, bool cleanUp)
        {
            bool firstTime = true;

            var e = eFirst; do
            {
                Debug.Assert(Geom.VertLeq(e._Org, e._Dst));
                AddRegionBelow(regUp, e._Sym);
                e = e._Onext;
            } while (e != eLast);

            // Walk *all* right-going edges from e.Org, in the dictionary order,
            // updating the winding numbers of each region, and re-linking the mesh
            // edges to match the dictionary ordering (if necessary).
            if (eTopLeft == null)
            {
                eTopLeft = RegionBelow(regUp)._eUp._Rprev;
            }

            ActiveRegion regPrev = regUp, reg;
            var ePrev = eTopLeft;
            while (true)
            {
                reg = RegionBelow(regPrev);
                e = reg._eUp._Sym;
                if (e._Org != ePrev._Org) break;

                if (e._Onext != ePrev)
                {
                    // Unlink e from its current position, and relink below ePrev
                    _mesh.Splice(e._Oprev, e);
                    _mesh.Splice(ePrev._Oprev, e);
                }
                // Compute the winding number and "inside" flag for the new regions
                reg._windingNumber = regPrev._windingNumber - e._winding;
                reg._inside = Geom.IsWindingInside(_windingRule, reg._windingNumber);

                // Check for two outgoing edges with same slope -- process these
                // before any intersection tests (see example in tessComputeInterior).
                regPrev._dirty = true;
                if (!firstTime && CheckForRightSplice(regPrev))
                {
                    Geom.AddWinding(e, ePrev);
                    DeleteRegion(regPrev);
                    _mesh.Delete(ePrev);
                }
                firstTime = false;
                regPrev = reg;
                ePrev = e;
            }
            regPrev._dirty = true;
            Debug.Assert(regPrev._windingNumber - e._winding == reg._windingNumber);

            if (cleanUp)
            {
                // Check for intersections between newly adjacent edges.
                WalkDirtyRegions(regPrev);
            }
        }
Exemplo n.º 59
0
 public static Real VertL1dist(MeshUtils.Vertex u, MeshUtils.Vertex v)
 {
     return Math.Abs(u._s - v._s) + Math.Abs(u._t - v._t);
 }
Exemplo n.º 60
0
        /// <summary>
        /// Purpose: connect a "left" vertex (one where both edges go right)
        /// to the processed portion of the mesh.  Let R be the active region
        /// containing vEvent, and let U and L be the upper and lower edge
        /// chains of R.  There are two possibilities:
        /// 
        /// - the normal case: split R into two regions, by connecting vEvent to
        ///   the rightmost vertex of U or L lying to the left of the sweep line
        /// 
        /// - the degenerate case: if vEvent is close enough to U or L, we
        ///   merge vEvent into that edge chain.  The subcases are:
        ///     - merging with the rightmost vertex of U or L
        ///     - merging with the active edge of U or L
        ///     - merging with an already-processed portion of U or L
        /// </summary>
        private void ConnectLeftVertex(MeshUtils.Vertex vEvent)
        {
            var tmp = new ActiveRegion();

            // Get a pointer to the active region containing vEvent
            tmp._eUp = vEvent._anEdge._Sym;
            var regUp = _dict.Find(tmp).Key;
            var regLo = RegionBelow(regUp);
            if (regLo == null)
            {
                // This may happen if the input polygon is coplanar.
                return;
            }
            var eUp = regUp._eUp;
            var eLo = regLo._eUp;

            // Try merging with U or L first
            if (Geom.EdgeSign(eUp._Dst, vEvent, eUp._Org) == 0.0f)
            {
                ConnectLeftDegenerate(regUp, vEvent);
                return;
            }

            // Connect vEvent to rightmost processed vertex of either chain.
            // e._Dst is the vertex that we will connect to vEvent.
            var reg = Geom.VertLeq(eLo._Dst, eUp._Dst) ? regUp : regLo;

            if (regUp._inside || reg._fixUpperEdge)
            {
                MeshUtils.Edge eNew;
                if (reg == regUp)
                {
                    eNew = _mesh.Connect(vEvent._anEdge._Sym, eUp._Lnext);
                }
                else
                {
                    eNew = _mesh.Connect(eLo._Dnext, vEvent._anEdge)._Sym;
                }
                if (reg._fixUpperEdge)
                {
                    FixUpperEdge(reg, eNew);
                }
                else
                {
                    ComputeWinding(AddRegionBelow(regUp, eNew));
                }
                SweepEvent(vEvent);
            }
            else
            {
                // The new vertex is in a region which does not belong to the polygon.
                // We don't need to connect this vertex to the rest of the mesh.
                AddRightEdges(regUp, vEvent._anEdge, vEvent._anEdge, null, true);
            }
        }