//------------------------------------------------------------------------- public bool SetupBinaryImageAndIslands(out int numColliderRegions, out object spriteCollectionDefinition, object spriteCollection, int spriteID) { numColliderRegions = 0; spriteCollectionDefinition = null; mMainTex = GetTextureRef(spriteCollection, spriteID); if (mMainTex == null) { //Debug.LogError("No sprite texture found at sprite '" + tk2dSpriteComponent.name + "' with spriteID " + spriteID + "."); Debug.LogError("No sprite texture found at sprite with spriteID " + spriteID + "."); return(false); } spriteCollectionDefinition = GetTK2DSpriteCollectionDefinition(spriteCollection, spriteID); if (spriteCollectionDefinition == null) { // last error is already set in GetTK2DSpriteCollectionDefinition() above. return(false); } if (mOutlineAlgorithm == null) { mOutlineAlgorithm = new PolygonOutlineFromImageFrontend(); } int regionXOffset = 0; int regionYOffset = 0; int regionWidth = UsedTexture.width; int regionHeight = UsedTexture.height; bool isRegionUsed = false; if (mRegionIndependentParameters.CustomTex == null) { isRegionUsed = ReadRegionParameters(out regionXOffset, out regionYOffset, out regionWidth, out regionHeight, spriteCollectionDefinition); regionYOffset = mMainTex.height - regionYOffset - regionHeight; } mOutlineAlgorithm.BinaryAlphaThresholdImageFromTexture(ref mBinaryImage, out mBinaryImageWidth, out mBinaryImageHeight, UsedTexture, mRegionIndependentParameters.AlphaOpaqueThreshold, isRegionUsed, regionXOffset, regionYOffset, regionWidth, regionHeight); int imageSize = mBinaryImageWidth * mBinaryImageHeight; if (mClassificationImage == null || mClassificationImage.Length < imageSize) { mClassificationImage = new int[imageSize]; } bool anyIslandsFound = CalculateIslandStartingPoints(mBinaryImage, mBinaryImageWidth, mBinaryImageHeight, ref mClassificationImage, ref mIslands, ref mSeaRegions); if (!anyIslandsFound) { return(false); } AlphaMeshCollider.SetupColliderRegions(out mColliderRegions, mIslands, mSeaRegions); numColliderRegions = mColliderRegions.Length; SetupColliderRegionParameters(ref mColliderRegionParameters, mRegionIndependentParameters.DefaultMaxPointCount, mIslands, mSeaRegions); return(true); }
//------------------------------------------------------------------------- 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; } } }
//------------------------------------------------------------------------- bool GenerateUnreducedColliderMesh() { if (NeedsToCopyRegionIndependentParametersForBackwardsCompatibility()) { CopyParametersToRegionIndependentParametersForBackwardsCompatibility(ref this.mRegionIndependentParameters, this); } // just in case the texture has changed. InitTextureParams(); if (mHasSmoothMovesAnimBoneColliderComponent || mHasSmoothMovesBoneAnimationParent == InitState.Yes) { EnsureSmoothMovesBoneAnimHasRestoreComponent(mSmoothMovesBoneAnimation); } if (UsedTexture == null) { return false; } UpdateColliderMeshFilename(); if (mOutlineAlgorithm == null) { mOutlineAlgorithm = new PolygonOutlineFromImageFrontend(); } bool useImageRegion = false; int regionX = 0; int regionY = 0; int regionWidth = UsedTexture.width; int regionHeight = UsedTexture.height; float unroundedRegionX = 0.0f; float unroundedRegionY = 0.0f; float unroundedWidth = 1.0f; float unroundedHeight = 1.0f; float pixelCutawayLeft = 0.0f; float pixelCutawayRight = 0.0f; float pixelCutawayBottom = 0.0f; float pixelCutawayTop = 0.0f; if (mRegionIndependentParameters.IsCustomAtlasRegionUsed || mIsAtlasUsed) { useImageRegion = true; if (mRegionIndependentParameters.IsCustomAtlasRegionUsed) { unroundedRegionX = mRegionIndependentParameters.CustomAtlasFramePositionInPixels.x; unroundedRegionY = mRegionIndependentParameters.CustomAtlasFramePositionInPixels.y; unroundedWidth = mRegionIndependentParameters.CustomAtlasFrameSizeInPixels.x; unroundedHeight = mRegionIndependentParameters.CustomAtlasFrameSizeInPixels.y; } else if (mIsAtlasUsed) { // mRegionIndependentParameters.IsCustomAtlasRegionUsed has priority over mIsAtlasUsed. unroundedRegionX = mAtlasFramePositionInPixels.x; unroundedRegionY = mAtlasFramePositionInPixels.y; unroundedWidth = mAtlasFrameSizeInPixels.x; unroundedHeight = mAtlasFrameSizeInPixels.y; } regionX = Mathf.FloorToInt(unroundedRegionX); regionY = Mathf.FloorToInt(unroundedRegionY); float unroundedEndX = unroundedRegionX + unroundedWidth; float unroundedEndY = unroundedRegionY + unroundedHeight; int endX = Mathf.CeilToInt(unroundedEndX); int endY = Mathf.CeilToInt(unroundedEndY); regionWidth = endX - regionX; regionHeight = endY - regionY; pixelCutawayLeft = unroundedRegionX - regionX; pixelCutawayRight = endX - unroundedEndX; pixelCutawayBottom = endY - unroundedEndY; pixelCutawayTop = unroundedRegionY - regionY; } if (regionWidth == 0 || regionHeight == 0) { Debug.LogError("Error: Encountered image width or height of 0. Stopping collider generation."); return false; } bool wasSuccessful = mOutlineAlgorithm.BinaryAlphaThresholdImageFromTexture(out mBinaryImage, UsedTexture, mRegionIndependentParameters.AlphaOpaqueThreshold, useImageRegion, regionX, regionY, regionWidth, regionHeight); if (!wasSuccessful) { Debug.LogError(mOutlineAlgorithm.LastError); return false; } bool anyIslandsFound = CalculateIslandStartingPoints(mBinaryImage, out mIslands, out mSeaRegions); if (!anyIslandsFound) { return false; } SetupColliderRegions(out mColliderRegions, mIslands, mSeaRegions); SetupColliderRegionParameters(ref mColliderRegionParameters, mRegionIndependentParameters.DefaultMaxPointCount, mIslands, mSeaRegions); CopyOldPointCountParameterToFirstIslandForBackwardsCompatibility(ref mColliderRegionParameters, ref mMaxPointCount); bool ccwVertexOrder = IsOutlineInCCWOrderNecessary(); mOutlineAlgorithm.RegionPixelCutawayLeft = pixelCutawayLeft; mOutlineAlgorithm.RegionPixelCutawayRight = pixelCutawayRight; mOutlineAlgorithm.RegionPixelCutawayBottom = pixelCutawayBottom; mOutlineAlgorithm.RegionPixelCutawayTop = pixelCutawayTop; mOutlineAlgorithm.NormalizeResultToCutRegion = true; CalculateUnreducedOutlineForAllColliderRegions(ref mColliderRegions, ref mOutlineAlgorithm, mRegionIndependentParameters, mColliderRegionParameters, mBinaryImage, ccwVertexOrder); 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; } } }
//------------------------------------------------------------------------- public bool SetupBinaryImageAndIslands(out int numColliderRegions, out object spriteCollectionDefinition, object spriteCollection, int spriteID) { numColliderRegions = 0; spriteCollectionDefinition = null; mMainTex = GetTextureRef(spriteCollection, spriteID); if (mMainTex == null) { //Debug.LogError("No sprite texture found at sprite '" + tk2dSpriteComponent.name + "' with spriteID " + spriteID + "."); Debug.LogError("No sprite texture found at sprite with spriteID " + spriteID + "."); return false; } spriteCollectionDefinition = GetTK2DSpriteCollectionDefinition(spriteCollection, spriteID); if (spriteCollectionDefinition == null) { // last error is already set in GetTK2DSpriteCollectionDefinition() above. return false; } if (mOutlineAlgorithm == null) { mOutlineAlgorithm = new PolygonOutlineFromImageFrontend(); } int regionXOffset = 0; int regionYOffset = 0; int regionWidth = UsedTexture.width; int regionHeight = UsedTexture.height; bool isRegionUsed = false; if (mRegionIndependentParameters.CustomTex == null) { isRegionUsed = ReadRegionParameters(out regionXOffset, out regionYOffset, out regionWidth, out regionHeight, spriteCollectionDefinition); regionYOffset = mMainTex.height - regionYOffset - regionHeight; } mOutlineAlgorithm.BinaryAlphaThresholdImageFromTexture(out mBinaryImage, UsedTexture, mRegionIndependentParameters.AlphaOpaqueThreshold, isRegionUsed, regionXOffset, regionYOffset, regionWidth, regionHeight); bool anyIslandsFound = CalculateIslandStartingPoints(mBinaryImage, out mIslands, out mSeaRegions); if (!anyIslandsFound) { return false; } AlphaMeshCollider.SetupColliderRegions(out mColliderRegions, mIslands, mSeaRegions); numColliderRegions = mColliderRegions.Length; SetupColliderRegionParameters(ref mColliderRegionParameters, mRegionIndependentParameters.DefaultMaxPointCount, mIslands, mSeaRegions); 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; } } }
//------------------------------------------------------------------------- public void CopyColliderRegionsForBackwardsCompatibility() { mGeneratedColliderData[0].mOutlineAlgorithm = this.mOutlineAlgorithm; mGeneratedColliderData[0].mBinaryImage = this.mBinaryImage; mGeneratedColliderData[0].mColliderRegions = this.mColliderRegions; this.mOutlineAlgorithm = null; this.mBinaryImage = null; this.mColliderRegions = null; }