//------------------------------------------------------------------------- public static void CalculateUnreducedOutlineForAllColliderRegions(ref ColliderRegionData[] colliderRegions, ref PolygonOutlineFromImageFrontend outlineAlgorithm, RegionIndependentParameters regionIndependentParameters, ColliderRegionParameters[] colliderRegionParameters, bool [,] binaryImage, bool ccwVertexOrder) { for (int count = 0; count < colliderRegions.Length; ++count) { if (colliderRegionParameters[count].EnableRegion) { // Calculate polygon bounds outlineAlgorithm.VertexReductionDistanceTolerance = regionIndependentParameters.VertexReductionDistanceTolerance; outlineAlgorithm.MaxPointCount = colliderRegionParameters[count].MaxPointCount; bool allRegionsConvex = regionIndependentParameters.Convex; outlineAlgorithm.Convex = allRegionsConvex ? true : colliderRegionParameters[count].Convex; //outlineAlgorithm.Convex = colliderRegionParameters[count].Convex; outlineAlgorithm.XOffsetNormalized = -0.5f;//-this.transform.localScale.x / 2.0f; outlineAlgorithm.YOffsetNormalized = -0.5f;//-this.transform.localScale.y / 2.0f; bool outputInNormalizedSpace = true; bool regionVertexOrder = ccwVertexOrder; if (!colliderRegions[count].mRegionIsIsland) { regionVertexOrder = !regionVertexOrder; } colliderRegions[count].mOutlineVertexOrderIsCCW = regionVertexOrder; outlineAlgorithm.UnreducedOutlineFromBinaryImage(out colliderRegions[count].mIntermediateOutlineVertices, binaryImage, colliderRegions[count].mDetectedRegion.mPointAtBorder, colliderRegions[count].mRegionIsIsland, outputInNormalizedSpace, regionVertexOrder); } else { colliderRegions[count].mIntermediateOutlineVertices = null; colliderRegions[count].mResultVertices = null; colliderRegions[count].mResultTriangleIndices = null; } } }
//------------------------------------------------------------------------- static public void UpdateSimilarCollidersColliderData(string colliderMeshPathToReload, ColliderRegionData[] colliderRegions) { #if UNITY_4_AND_LATER object[] alphaMeshColliders = GameObject.FindObjectsOfType(typeof(AlphaMeshCollider)); #else object[] alphaMeshColliders = GameObject.FindSceneObjectsOfType(typeof(AlphaMeshCollider)); #endif foreach (AlphaMeshCollider collider in alphaMeshColliders) { if (collider.FullColliderMeshPath().Equals(colliderMeshPathToReload)) { collider.mColliderRegions = colliderRegions; } } }
//------------------------------------------------------------------------- public static void SetupColliderRegions(out ColliderRegionData[] colliderRegions, IslandDetector.Region[] islands, IslandDetector.Region[] seaRegions) { int numColliderRegions = islands.Length + seaRegions.Length; colliderRegions = new ColliderRegionData[numColliderRegions]; int colliderRegionIndex = 0; foreach (IslandDetector.Region islandRegion in islands) { ColliderRegionData newRegion = new ColliderRegionData(); newRegion.mDetectedRegion = islandRegion; newRegion.mRegionIsIsland = true; colliderRegions[colliderRegionIndex++] = newRegion; } foreach (IslandDetector.Region seaRegion in seaRegions) { ColliderRegionData newRegion = new ColliderRegionData(); newRegion.mDetectedRegion = seaRegion; newRegion.mRegionIsIsland = false; colliderRegions[colliderRegionIndex++] = newRegion; } }
//------------------------------------------------------------------------- static bool JoinVertexGroups(ColliderRegionData[] regions, out Vector3[] jointVertices, out int[] jointIndices) { int numVertices = 0; int numIndices = 0; for (int count = 0; count < regions.Length; ++count) { if (regions[count].mResultVertices == null || regions[count].mResultTriangleIndices == null) { continue; } numVertices += regions[count].mResultVertices.Length; numIndices += regions[count].mResultTriangleIndices.Length; } jointVertices = new Vector3[numVertices]; jointIndices = new int[numIndices]; int jointVertexIndex = 0; int jointIndexIndex = 0; int indexOffset = 0; for (int regionIndex = 0; regionIndex < regions.Length; ++regionIndex) { if (regions[regionIndex].mResultVertices == null || regions[regionIndex].mResultTriangleIndices == null) { continue; } Vector3[] regionVertices = regions[regionIndex].mResultVertices; int[] regionIndices = regions[regionIndex].mResultTriangleIndices; for (int regionVertexIndex = 0; regionVertexIndex < regionVertices.Length; ++regionVertexIndex) { jointVertices[jointVertexIndex++] = regionVertices[regionVertexIndex]; } for (int regionIndexIndex = 0; regionIndexIndex < regionIndices.Length; ++regionIndexIndex) { jointIndices[jointIndexIndex++] = regionIndices[regionIndexIndex] + indexOffset; } indexOffset += regionVertices.Length; } return true; }
//------------------------------------------------------------------------- public static int ReduceOutlineForAllColliderRegions(ref ColliderRegionData[] colliderRegions, ref PolygonOutlineFromImageFrontend outlineAlgorithm, RegionIndependentParametersTK2D regionIndependentParameters, ColliderRegionParametersTK2D[] colliderRegionParameters) { int numRegionsWithData = 0; if (colliderRegions == null || colliderRegions.Length == 0 || outlineAlgorithm == null) { Debug.LogError("Error: Unexpected state in ReduceOutlineForAllColliderRegions(): colliderRegions is empty or null or outlineAlgorithm is null!"); return 0; } for (int count = 0; count < colliderRegions.Length; ++count) { if (colliderRegions[count].mIntermediateOutlineVertices == null) { colliderRegions[count].mResultVertices = null; colliderRegions[count].mResultTriangleIndices = null; continue; } if (colliderRegions[count].mReducedOutlineVertices != null && !colliderRegionParameters[count].RegionUpdateCalculationNeeded) { continue; } outlineAlgorithm.VertexReductionDistanceTolerance = regionIndependentParameters.VertexReductionDistanceTolerance; outlineAlgorithm.MaxPointCount = colliderRegionParameters[count].MaxPointCount; // TODO: replace this with a joint-convex hull implementation, just a workaround for now. bool allRegionsConvex = regionIndependentParameters.Convex; outlineAlgorithm.Convex = allRegionsConvex ? true : colliderRegionParameters[count].Convex; colliderRegions[count].mReducedOutlineVertices = outlineAlgorithm.ReduceOutline(colliderRegions[count].mIntermediateOutlineVertices, colliderRegions[count].mOutlineVertexOrderIsCCW); colliderRegionParameters[count].RegionUpdateCalculationNeeded = false; ++numRegionsWithData; } return numRegionsWithData; }
//------------------------------------------------------------------------- public static void CalculateUnreducedOutlineForAllColliderRegions(ref ColliderRegionData[] colliderRegions, ref PolygonOutlineFromImageFrontend outlineAlgorithm, RegionIndependentParametersTK2D regionIndependentParameters, ColliderRegionParametersTK2D[] colliderRegionParameters, bool [,] binaryImage, bool ccwVertexOrder) { Vector3 customOffset = regionIndependentParameters.CustomOffset; Vector3 customScale = regionIndependentParameters.CustomScale; for (int count = 0; count < colliderRegions.Length; ++count) { if (colliderRegionParameters[count].EnableRegion) { // Calculate polygon bounds outlineAlgorithm.VertexReductionDistanceTolerance = regionIndependentParameters.VertexReductionDistanceTolerance; outlineAlgorithm.MaxPointCount = colliderRegionParameters[count].MaxPointCount; // TODO: replace this with a joint-convex hull implementation, just a workaround for now. bool allRegionsConvex = regionIndependentParameters.Convex; outlineAlgorithm.Convex = allRegionsConvex ? true : colliderRegionParameters[count].Convex; //outlineAlgorithm.Convex = colliderRegionParameters[count].Convex; outlineAlgorithm.XOffsetNormalized = 0.0f + customOffset.x + (0.5f - (0.5f * customScale.x)); outlineAlgorithm.YOffsetNormalized = 1.0f - customOffset.y - (0.5f - (0.5f * customScale.y)); outlineAlgorithm.XScale = 1.0f * customScale.x; outlineAlgorithm.YScale = -1.0f * customScale.y; bool outputVerticesInNormalizedSpace = false; bool regionVertexOrder = ccwVertexOrder; if (!colliderRegions[count].mRegionIsIsland) { regionVertexOrder = !regionVertexOrder; } colliderRegions[count].mOutlineVertexOrderIsCCW = regionVertexOrder; outlineAlgorithm.UnreducedOutlineFromBinaryImage(out colliderRegions[count].mIntermediateOutlineVertices, binaryImage, colliderRegions[count].mDetectedRegion.mPointAtBorder, colliderRegions[count].mRegionIsIsland, outputVerticesInNormalizedSpace, regionVertexOrder); } else { colliderRegions[count].mIntermediateOutlineVertices = null; colliderRegions[count].mResultVertices = null; colliderRegions[count].mResultTriangleIndices = null; } } }
//------------------------------------------------------------------------- void OnInspectorGuiHolesAndIslandsSection(out bool haveColliderRegionEnabledChanged, out bool haveColliderRegionMaxPointCountChanged, out bool haveColliderRegionConvexChanged) { haveColliderRegionEnabledChanged = false; haveColliderRegionMaxPointCountChanged = false; haveColliderRegionConvexChanged = false; if (mAlgorithmHelper.ColliderRegions == null || mAlgorithmHelper.ColliderRegions.Length == 0 || mAlgorithmHelper.ColliderRegionParams == null || mAlgorithmHelper.ColliderRegionParams.Length == 0) { return; } if (!mAllSelectedSpritesHaveSameNumColliderRegions) { EditorGUILayout.LabelField("Holes and Islands", "<different number of Holes/Islands>"); return; } int numColliderRegions = 0; if (mAlgorithmHelper.ColliderRegions != null) { numColliderRegions = mAlgorithmHelper.ColliderRegions.Length; } bool[] newIsRegionEnabled = new bool [numColliderRegions]; int[] newRegionPointCount = new int [numColliderRegions]; bool[] newForceRegionConvex = new bool [numColliderRegions]; string foldoutString = "Holes and Islands [" + mAlgorithmHelper.NumEnabledColliderRegions + "][" + mAlgorithmHelper.ActualPointCountOfAllRegions + " vertices]"; mShowHolesAndIslandsSection = EditorGUILayout.Foldout(mShowHolesAndIslandsSection, foldoutString); if (mShowHolesAndIslandsSection) { EditorGUI.indentLevel++; for (int regionIndex = 0; regionIndex < numColliderRegions; ++regionIndex) { ColliderRegionData colliderRegion = mAlgorithmHelper.ColliderRegions[regionIndex]; ColliderRegionParametersTK2D parameters = mAlgorithmHelper.ColliderRegionParams[regionIndex]; bool isEnabled = parameters.EnableRegion; int maxPointCount = parameters.MaxPointCount; bool convex = parameters.Convex; if (regionIndex != 0) { EditorGUILayout.Space(); } string regionOrIslandString = colliderRegion.mRegionIsIsland ? "Island " : "Hole "; regionOrIslandString += regionIndex + " [" + colliderRegion.mDetectedRegion.mPointCount + " px]"; //EditorGUILayout.BeginToggleGroup(regionOrIslandString, true); bool newIsEnabled = EditorGUILayout.BeginToggleGroup(regionOrIslandString, isEnabled); //bool newIsEnabled = EditorGUILayout.Toggle(regionOrIslandString, isEnabled); EditorGUI.indentLevel++; // int [3..100] max point count int newPointCount = EditorGUILayout.IntSlider("Outline Vertex Count", maxPointCount, 3, mPointCountSliderMax); bool newConvex = EditorGUILayout.Toggle("Force Convex", convex); EditorGUI.indentLevel--; EditorGUILayout.EndToggleGroup(); bool hasEnabledChanged = newIsEnabled != isEnabled; bool hasPountCountChanged = newPointCount != maxPointCount; bool hasConvexChanged = newConvex != convex; if (hasEnabledChanged) { haveColliderRegionEnabledChanged = true; } if (hasPountCountChanged) { haveColliderRegionMaxPointCountChanged = true; } if (hasConvexChanged) { haveColliderRegionConvexChanged = true; } newIsRegionEnabled[regionIndex] = newIsEnabled; newRegionPointCount[regionIndex] = newPointCount; newForceRegionConvex[regionIndex] = newConvex; } for (int regionIndex = 0; regionIndex < numColliderRegions; ++regionIndex) { ColliderRegionParametersTK2D colliderRegionParams = mAlgorithmHelper.ColliderRegionParams[regionIndex]; colliderRegionParams.EnableRegion = newIsRegionEnabled[regionIndex]; colliderRegionParams.MaxPointCount = newRegionPointCount[regionIndex]; colliderRegionParams.Convex = newForceRegionConvex[regionIndex]; } EditorGUI.indentLevel--; } }