private static void DrawFacadeTexture(TexturePaintObject[] sourceTextures, Vector2 bayBase, Vector2 bayDimensions, int subMesh, bool flipped, Rect packedPosition) { int scaledPadding = Mathf.FloorToInt(ATLAS_PADDING * packedScale); int paintWidth = Mathf.RoundToInt(bayDimensions.x * PIXELS_PER_METER * packedScale); int paintHeight = Mathf.RoundToInt(bayDimensions.y * PIXELS_PER_METER * packedScale); TexturePaintObject paintObject = sourceTextures[subMesh]; Color32[] sourceColours = paintObject.pixels; int sourceWidth = paintObject.width; int sourceHeight = paintObject.height; int sourceSize = sourceColours.Length; Vector2 textureStretch = Vector2.one * packedScale; if (!paintObject.tiled) { textureStretch.x = (float)sourceWidth / (float)paintWidth; textureStretch.y = (float)sourceHeight / (float)paintHeight; } int baseX = Mathf.RoundToInt((bayBase.x * PIXELS_PER_METER) * packedScale + packedPosition.x); int baseY = Mathf.RoundToInt((bayBase.y * PIXELS_PER_METER) * packedScale + packedPosition.y); int baseCood = baseX + baseY * textureWidth; //fill in a little bit more to cover rounding errors paintWidth++; paintHeight++; int useWidth = !flipped ? paintWidth : paintHeight; int useHeight = !flipped ? paintHeight : paintWidth; for (int px = 0; px < useWidth; px++) { for (int py = 0; py < useHeight; py++) { int paintPixelIndex = (!flipped) ? px + py * textureWidth : py + px * textureWidth; int six, siy; if (paintObject.tiled) { six = px % sourceWidth; siy = py % sourceHeight; } else { six = Mathf.RoundToInt(px * textureStretch.x * paintObject.tiles.x) % sourceWidth; siy = Mathf.RoundToInt(py * textureStretch.y * paintObject.tiles.y) % sourceHeight; } int sourceIndex = Mathf.Clamp(six + siy * sourceWidth, 0, sourceSize - 1); int pixelCoord = Mathf.Clamp(baseCood + paintPixelIndex, 0, textureSize - 1); Color32 sourceColour = sourceColours[sourceIndex]; colourArray[pixelCoord] = sourceColour; //Padding if (bayBase.x == 0 && px == 0) { for (int p = 1; p < scaledPadding; p++) { int paintCoord = pixelCoord - p; if (paintCoord < 0) { break; } colourArray[paintCoord] = sourceColour; } } if ((baseX + paintWidth) > packedPosition.xMax && px == useWidth - 1) { for (int p = 1; p < scaledPadding; p++) { int paintCoord = pixelCoord + p; if (paintCoord >= textureSize) { break; } colourArray[paintCoord] = sourceColour; } } if (bayBase.y == 0 && py == 0) { for (int p = 1; p < scaledPadding; p++) { int paintCoord = pixelCoord - (p * textureWidth); if (paintCoord < 0) { break; } colourArray[paintCoord] = sourceColour; } } if ((baseY + paintHeight) > packedPosition.yMax && py == useHeight - 1) { for (int p = 1; p < scaledPadding; p++) { int paintCoord = pixelCoord + (p * textureWidth); if (paintCoord >= textureSize) { break; } colourArray[paintCoord] = sourceColour; } } } } }
private static void DrawFacadeTexture(TexturePaintObject[] sourceTextures, Vector2 bayBase, Vector2 bayDimensions, int subMesh, bool flipped, Rect packedPosition) { int scaledPadding = Mathf.FloorToInt(ATLAS_PADDING * packedScale); int paintWidth = Mathf.RoundToInt(bayDimensions.x * PIXELS_PER_METER * packedScale); int paintHeight = Mathf.RoundToInt(bayDimensions.y * PIXELS_PER_METER * packedScale); TexturePaintObject paintObject = sourceTextures[subMesh]; Color32[] sourceColours = paintObject.pixels; int sourceWidth = paintObject.width; int sourceHeight = paintObject.height; int sourceSize = sourceColours.Length; Vector2 textureStretch = Vector2.one * packedScale; if (!paintObject.tiled) { textureStretch.x = (float)sourceWidth / (float)paintWidth; textureStretch.y = (float)sourceHeight / (float)paintHeight; } int baseX = Mathf.RoundToInt((bayBase.x * PIXELS_PER_METER) * packedScale + packedPosition.x); int baseY = Mathf.RoundToInt((bayBase.y * PIXELS_PER_METER) * packedScale + packedPosition.y); int baseCood = baseX + baseY * textureWidth; //fill in a little bit more to cover rounding errors paintWidth++; paintHeight++; int useWidth = !flipped ? paintWidth : paintHeight; int useHeight = !flipped ? paintHeight : paintWidth; for (int px = 0; px < useWidth; px++) { for (int py = 0; py < useHeight; py++) { int paintPixelIndex = (!flipped) ? px + py * textureWidth : py + px * textureWidth; int six, siy; if (paintObject.tiled) { six = px % sourceWidth; siy = py % sourceHeight; } else { six = Mathf.RoundToInt(px * textureStretch.x * paintObject.tiles.x) % sourceWidth; siy = Mathf.RoundToInt(py * textureStretch.y * paintObject.tiles.y) % sourceHeight; } int sourceIndex = Mathf.Clamp(six + siy * sourceWidth, 0, sourceSize - 1); int pixelCoord = Mathf.Clamp(baseCood + paintPixelIndex, 0, textureSize - 1); Color32 sourceColour = sourceColours[sourceIndex]; colourArray[pixelCoord] = sourceColour; //Padding if (bayBase.x == 0 && px == 0) { for (int p = 1; p < scaledPadding; p++) { int paintCoord = pixelCoord - p; if (paintCoord < 0) break; colourArray[paintCoord] = sourceColour; } } if ((baseX + paintWidth) > packedPosition.xMax && px == useWidth - 1) { for (int p = 1; p < scaledPadding; p++) { int paintCoord = pixelCoord + p; if (paintCoord >= textureSize) break; colourArray[paintCoord] = sourceColour; } } if (bayBase.y == 0 && py == 0) { for (int p = 1; p < scaledPadding; p++) { int paintCoord = pixelCoord - (p * textureWidth); if (paintCoord < 0) break; colourArray[paintCoord] = sourceColour; } } if ((baseY + paintHeight) > packedPosition.yMax && py == useHeight - 1) { for (int p = 1; p < scaledPadding; p++) { int paintCoord = pixelCoord + (p * textureWidth); if (paintCoord >= textureSize) break; colourArray[paintCoord] = sourceColour; } } } } }
private static void BuildTextures() { List <TexturePaintObject> buildSourceTextures = new List <TexturePaintObject>(); foreach (BuildrTexture btexture in data.textures)//Gather the source textures, resized into Color32 arrays { TexturePaintObject texturePaintObject = new TexturePaintObject(); texturePaintObject.pixels = ((Texture2D)btexture.texture).GetPixels32(); texturePaintObject.width = btexture.texture.width; texturePaintObject.height = btexture.texture.height; texturePaintObject.tiles = new Vector2(btexture.tiledX, btexture.tiledY); if (btexture.tiled) { int resizedTextureWidth = Mathf.RoundToInt(btexture.textureUnitSize.x * PIXELS_PER_METER * packedScale); int resizedTextureHeight = Mathf.RoundToInt(btexture.textureUnitSize.y * PIXELS_PER_METER * packedScale); texturePaintObject.pixels = TextureScale.NearestNeighbourSample(texturePaintObject.pixels, texturePaintObject.width, texturePaintObject.height, resizedTextureWidth, resizedTextureHeight); texturePaintObject.width = resizedTextureWidth; texturePaintObject.height = resizedTextureHeight; } else { texturePaintObject.tiled = false; } buildSourceTextures.Add(texturePaintObject); } LogTimer("Gather Source into Arrays"); TexturePaintObject[] sourceTextures = buildSourceTextures.ToArray(); textures = data.textures.ToArray(); BuildrFacadeDesign facadeDesign = data.facades[0]; BuildrPlan plan = data.plan; int numberOfVolumes = data.plan.numberOfVolumes; int facadeNumber = 0; for (int s = 0; s < numberOfVolumes; s++) { BuildrVolume volume = plan.volumes[s]; int numberOfVolumePoints = volume.points.Count; for (int f = 0; f < numberOfVolumePoints; f++) { if (!volume.renderFacade[f]) { continue; } int indexA, indexB; Vector3 p0, p1; indexA = f; indexB = (f < numberOfVolumePoints - 1) ? f + 1 : 0; p0 = plan.points[volume.points[indexA]].vector3; p1 = plan.points[volume.points[indexB]].vector3; Rect packedPosition = packedTexturePositions[facadeNumber]; float facadeWidth = Vector3.Distance(p0, p1); int floorBase = plan.GetFacadeFloorHeight(s, volume.points[indexA], volume.points[indexB]); int numberOfFloors = volume.numberOfFloors - floorBase; if (numberOfFloors < 1) { //no facade - adjacent facade is taller and covers this one continue; } float floorHeight = data.floorHeight; BuildrVolumeStylesUnit[] styleUnits = volume.styles.GetContentsByFacade(volume.points[indexA]); int floorPatternSize = 0; List <int> facadePatternReference = new List <int>(); //this contains a list of all the facade style indices to refence when looking for the appropriate style per floor int patternCount = 0; foreach (BuildrVolumeStylesUnit styleUnit in styleUnits) //need to knw how big all the styles are together so we can loop through them { floorPatternSize += styleUnit.floors; for (int i = 0; i < styleUnit.floors; i++) { facadePatternReference.Add(patternCount); } patternCount++; } facadePatternReference.Reverse(); int rows = numberOfFloors; Vector2 bayBase = Vector2.zero; float currentFloorBase = 0; for (int r = 0; r < rows; r++) { currentFloorBase = floorHeight * r; int modFloor = (r % floorPatternSize); facadeDesign = data.facades[styleUnits[facadePatternReference[modFloor]].styleID]; bool isBlankWall = !facadeDesign.hasWindows; if (facadeDesign.type == BuildrFacadeDesign.types.patterned) { BuildrBay firstBay = data.bays[facadeDesign.bayPattern[0]]; if (firstBay.openingWidth > facadeWidth) { isBlankWall = true; } if (facadeDesign.bayPattern.Count == 0) { isBlankWall = true; } } else { if (facadeDesign.simpleBay.openingWidth + facadeDesign.simpleBay.minimumBayWidth > facadeWidth) { isBlankWall = true; } } if (!isBlankWall) { float patternSize = 0;//the space the pattern fills, there will be a gap that will be distributed to all bay styles int numberOfBays = 0; BuildrBay[] bays; int numberOfBayDesigns = 0; if (facadeDesign.type == BuildrFacadeDesign.types.patterned) { numberOfBayDesigns = facadeDesign.bayPattern.Count; bays = new BuildrBay[numberOfBayDesigns]; for (int i = 0; i < numberOfBayDesigns; i++) { bays[i] = data.bays[facadeDesign.bayPattern[i]]; } } else { bays = new[] { facadeDesign.simpleBay }; numberOfBayDesigns = 1; } //start with first window width - we'll be adding to this until we have filled the facade width int it = 100; while (true) { int patternModIndex = numberOfBays % numberOfBayDesigns; float patternAddition = bays[patternModIndex].openingWidth + bays[patternModIndex].minimumBayWidth; if (patternSize + patternAddition < facadeWidth) { patternSize += patternAddition; numberOfBays++; } else { break; } it--; if (it < 0) { break; } } float perBayAdditionalSpacing = (facadeWidth - patternSize) / numberOfBays; float windowXBase = 0; for (int c = 0; c < numberOfBays; c++) { BuildrBay bayStyle; if (facadeDesign.type == BuildrFacadeDesign.types.patterned) { int numberOfBayStyles = facadeDesign.bayPattern.Count; bayStyle = bays[c % numberOfBayStyles]; } else { bayStyle = facadeDesign.simpleBay; } float actualWindowSpacing = bayStyle.minimumBayWidth + perBayAdditionalSpacing; float leftSpace = actualWindowSpacing * bayStyle.openingWidthRatio; float rightSpace = actualWindowSpacing - leftSpace; float openingSpace = bayStyle.openingWidth; Vector3 bayDimensions; int subMesh; bool flipped; if (!bayStyle.isOpening) { subMesh = bayStyle.GetTexture(BuildrBay.TextureNames.WallTexture); flipped = bayStyle.IsFlipped(BuildrBay.TextureNames.WallTexture); bayBase.x = windowXBase; bayBase.y = currentFloorBase; float bayWidth = (openingSpace + actualWindowSpacing); float bayHeight = floorHeight; bayDimensions = new Vector2(bayWidth, bayHeight); DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition); windowXBase += bayWidth; //move base vertor to next bay continue; //bay filled - move onto next bay } float rowBottomHeight = ((floorHeight - bayStyle.openingHeight) * bayStyle.openingHeightRatio); float rowTopHeight = (floorHeight - rowBottomHeight - bayStyle.openingHeight); //Window subMesh = bayStyle.GetTexture(BuildrBay.TextureNames.OpeningBackTexture); flipped = bayStyle.IsFlipped(BuildrBay.TextureNames.OpeningBackTexture); bayBase.x = windowXBase + leftSpace; bayBase.y = currentFloorBase + rowBottomHeight; bayDimensions = new Vector2(bayStyle.openingWidth, bayStyle.openingHeight); DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition); //Column Left if (leftSpace > 0) { subMesh = bayStyle.GetTexture(BuildrBay.TextureNames.ColumnTexture); flipped = bayStyle.IsFlipped(BuildrBay.TextureNames.ColumnTexture); bayBase.x = windowXBase; bayBase.y = currentFloorBase + rowBottomHeight; bayDimensions = new Vector2(leftSpace, bayStyle.openingHeight); DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition); } //Column Right if (rightSpace > 0) { subMesh = bayStyle.GetTexture(BuildrBay.TextureNames.ColumnTexture); flipped = bayStyle.IsFlipped(BuildrBay.TextureNames.ColumnTexture); bayBase.x = windowXBase + leftSpace + openingSpace; bayBase.y = currentFloorBase + rowBottomHeight; bayDimensions = new Vector2(rightSpace, bayStyle.openingHeight); DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition); } //Row Bottom if (rowBottomHeight > 0) { subMesh = bayStyle.GetTexture(BuildrBay.TextureNames.RowTexture); flipped = bayStyle.IsFlipped(BuildrBay.TextureNames.RowTexture); bayBase.x = windowXBase + leftSpace; bayBase.y = currentFloorBase; bayDimensions = new Vector2(openingSpace, rowBottomHeight); DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition); } //Row Top if (rowTopHeight > 0) { subMesh = bayStyle.GetTexture(BuildrBay.TextureNames.RowTexture); flipped = bayStyle.IsFlipped(BuildrBay.TextureNames.RowTexture); bayBase.x = windowXBase + leftSpace; bayBase.y = currentFloorBase + rowBottomHeight + bayStyle.openingHeight; bayDimensions = new Vector2(openingSpace, rowTopHeight); DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition); } //Cross Left if (leftSpace > 0) { //Cross Left Bottom subMesh = bayStyle.GetTexture(BuildrBay.TextureNames.CrossTexture); flipped = bayStyle.IsFlipped(BuildrBay.TextureNames.CrossTexture); bayBase.x = windowXBase; bayBase.y = currentFloorBase; bayDimensions = new Vector2(leftSpace, rowBottomHeight); DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition); //Cross Left Top subMesh = bayStyle.GetTexture(BuildrBay.TextureNames.CrossTexture); flipped = bayStyle.IsFlipped(BuildrBay.TextureNames.CrossTexture); bayBase.x = windowXBase; bayBase.y = currentFloorBase + rowBottomHeight + bayStyle.openingHeight; bayDimensions = new Vector2(leftSpace, rowTopHeight); DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition); } //Cross Right if (rightSpace > 0) { //Cross Left Bottom subMesh = bayStyle.GetTexture(BuildrBay.TextureNames.CrossTexture); flipped = bayStyle.IsFlipped(BuildrBay.TextureNames.CrossTexture); bayBase.x = windowXBase + leftSpace + openingSpace; bayBase.y = currentFloorBase; bayDimensions = new Vector2(rightSpace, rowBottomHeight); DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition); //Cross Left Top subMesh = bayStyle.GetTexture(BuildrBay.TextureNames.CrossTexture); flipped = bayStyle.IsFlipped(BuildrBay.TextureNames.CrossTexture); bayBase.x = windowXBase + leftSpace + openingSpace; bayBase.y = currentFloorBase + rowBottomHeight + bayStyle.openingHeight; bayDimensions = new Vector2(rightSpace, rowTopHeight); DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition); } windowXBase += leftSpace + openingSpace + rightSpace;//move base vertor to next bay } } else { // windowless wall int subMesh = facadeDesign.simpleBay.GetTexture(BuildrBay.TextureNames.WallTexture); bool flipped = facadeDesign.simpleBay.IsFlipped(BuildrBay.TextureNames.WallTexture); bayBase.x = 0; bayBase.y = currentFloorBase; Vector2 dimensions = new Vector2(facadeWidth, floorHeight); DrawFacadeTexture(sourceTextures, bayBase, dimensions, subMesh, flipped, packedPosition); } } facadeNumber++; } } LogTimer("generate facade textures"); //add roof textures int numberOfroofTextures = roofTextures.Count; int scaledPadding = Mathf.FloorToInt(ATLAS_PADDING * packedScale); for (int i = 0; i < numberOfroofTextures; i++) { Rect roofTexturePosition = packedTexturePositions[i + facadeNumber]; BuildrTexture bTexture = roofTextures[i]; int roofTextureWidth = bTexture.texture.width; int roofTextureHeight = bTexture.texture.height; int targetTextureWidth = Mathf.RoundToInt(roofTexturePosition.width); int targetTextureHeight = Mathf.RoundToInt(roofTexturePosition.height); if (bTexture.maxUVTile == Vector2.zero) { LogTimer("BuildTextures: Skip texture " + bTexture.name + " as it appears it's not used"); continue; } int sourceTextureWidth = Mathf.RoundToInt(targetTextureWidth / (bTexture.tiled ? bTexture.maxUVTile.x : bTexture.tiledX)); int sourceTextureHeight = Mathf.RoundToInt(targetTextureHeight / (bTexture.tiled ? bTexture.maxUVTile.y : bTexture.tiledY)); int sourceTextureSize = sourceTextureWidth * sourceTextureHeight; if (sourceTextureSize == 0) { //Debug.Log(sourceTextureWidth+" "+sourceTextureHeight+" "+bTexture.tiledX+" "+bTexture.maxUVTile+" "+bTexture.tiledX+","+bTexture.tiledY); continue; } Color32[] roofColourArray = TextureScale.NearestNeighbourSample(((Texture2D)bTexture.texture).GetPixels32(), roofTextureWidth, roofTextureHeight, sourceTextureWidth, sourceTextureHeight); //Color32[] roofColourArray = bTexture.texture.GetPixels32(); for (int x = 0; x < targetTextureWidth; x++) { for (int y = 0; y < targetTextureHeight; y++) { int drawX = Mathf.FloorToInt(x + roofTexturePosition.x); int drawY = Mathf.FloorToInt(y + roofTexturePosition.y); int colourIndex = drawX + drawY * textureWidth; int sx = x % sourceTextureWidth; int sy = y % sourceTextureHeight; int sourceIndex = sx + sy * sourceTextureWidth; if (sourceIndex >= sourceTextureSize) { Debug.Log("Source Index too big " + sx + " " + sy + " " + sourceTextureWidth + " " + sourceTextureSize + " " + bTexture.maxUVTile + " " + bTexture.name); } Color32 sourceColour = roofColourArray[sourceIndex]; if (colourIndex >= textureSize) { Debug.Log("Output Index Too big " + drawX + " " + drawY + " " + colourIndex + " " + textureSize + " " + roofTexturePosition); } colourArray[colourIndex] = sourceColour; //Padding if (x == 0) { for (int p = 0; p < scaledPadding; p++) { colourArray[colourIndex - p] = sourceColour; } } if (x == targetTextureWidth - 1) { for (int p = 0; p < scaledPadding; p++) { colourArray[colourIndex + p] = sourceColour; } } if (y == 0) { for (int p = 0; p < scaledPadding; p++) { colourArray[colourIndex - (p * textureWidth)] = sourceColour; } } if (y == targetTextureHeight - 1) { for (int p = 0; p < scaledPadding; p++) { colourArray[colourIndex + (p * textureWidth)] = sourceColour; } } } } } LogTimer("generate roof textures"); }
private static void BuildTextures() { List<TexturePaintObject> buildSourceTextures = new List<TexturePaintObject>(); foreach (BuildrTexture btexture in data.textures)//Gather the source textures, resized into Color32 arrays { TexturePaintObject texturePaintObject = new TexturePaintObject(); texturePaintObject.pixels = ((Texture2D)btexture.texture).GetPixels32(); texturePaintObject.width = btexture.texture.width; texturePaintObject.height = btexture.texture.height; texturePaintObject.tiles = new Vector2(btexture.tiledX, btexture.tiledY); if (btexture.tiled) { int resizedTextureWidth = Mathf.RoundToInt(btexture.textureUnitSize.x * PIXELS_PER_METER * packedScale); int resizedTextureHeight = Mathf.RoundToInt(btexture.textureUnitSize.y * PIXELS_PER_METER * packedScale); texturePaintObject.pixels = TextureScale.NearestNeighbourSample(texturePaintObject.pixels, texturePaintObject.width, texturePaintObject.height, resizedTextureWidth, resizedTextureHeight); texturePaintObject.width = resizedTextureWidth; texturePaintObject.height = resizedTextureHeight; } else { texturePaintObject.tiled = false; } buildSourceTextures.Add(texturePaintObject); } TexturePaintObject[] sourceTextures = buildSourceTextures.ToArray(); textures = data.textures.ToArray(); BuildrFacadeDesign facadeDesign = data.facades[0]; BuildrPlan plan = data.plan; int numberOfVolumes = data.plan.numberOfVolumes; int facadeNumber = 0; for (int s = 0; s < numberOfVolumes; s++) { BuildrVolume volume = plan.volumes[s]; int numberOfVolumePoints = volume.points.Count; for (int f = 0; f < numberOfVolumePoints; f++) { if (!volume.renderFacade[f]) continue; int indexA, indexB; Vector3 p0, p1; indexA = f; indexB = (f < numberOfVolumePoints - 1) ? f + 1 : 0; p0 = plan.points[volume.points[indexA]].vector3; p1 = plan.points[volume.points[indexB]].vector3; Rect packedPosition = packedTexturePositions[facadeNumber]; float facadeWidth = Vector3.Distance(p0, p1); int floorBase = plan.GetFacadeFloorHeight(s, volume.points[indexA], volume.points[indexB]); int numberOfFloors = volume.numberOfFloors - floorBase; if (numberOfFloors < 1) { //no facade - adjacent facade is taller and covers this one continue; } float floorHeight = data.floorHeight; BuildrVolumeStylesUnit[] styleUnits = volume.styles.GetContentsByFacade(volume.points[indexA]); int floorPatternSize = 0; List<int> facadePatternReference = new List<int>();//this contains a list of all the facade style indices to refence when looking for the appropriate style per floor int patternCount = 0; foreach (BuildrVolumeStylesUnit styleUnit in styleUnits)//need to knw how big all the styles are together so we can loop through them { floorPatternSize += styleUnit.floors; for (int i = 0; i < styleUnit.floors; i++) facadePatternReference.Add(patternCount); patternCount++; } facadePatternReference.Reverse(); int rows = numberOfFloors; Vector2 bayBase = Vector2.zero; float currentFloorBase = 0; for (int r = 0; r < rows; r++) { currentFloorBase = floorHeight * r; int modFloor = (r % floorPatternSize); facadeDesign = data.facades[styleUnits[facadePatternReference[modFloor]].styleID]; bool isBlankWall = !facadeDesign.hasWindows; if (facadeDesign.type == BuildrFacadeDesign.types.patterned) { BuildrBay firstBay = data.bays[facadeDesign.bayPattern[0]]; if (firstBay.openingWidth > facadeWidth) isBlankWall = true; if (facadeDesign.bayPattern.Count == 0) isBlankWall = true; } else { if (facadeDesign.simpleBay.openingWidth + facadeDesign.simpleBay.minimumBayWidth > facadeWidth) isBlankWall = true; } if (!isBlankWall) { float patternSize = 0;//the space the pattern fills, there will be a gap that will be distributed to all bay styles int numberOfBays = 0; BuildrBay[] bays; int numberOfBayDesigns = 0; if (facadeDesign.type == BuildrFacadeDesign.types.patterned) { numberOfBayDesigns = facadeDesign.bayPattern.Count; bays = new BuildrBay[numberOfBayDesigns]; for (int i = 0; i < numberOfBayDesigns; i++) { bays[i] = data.bays[facadeDesign.bayPattern[i]]; } } else { bays = new[] { facadeDesign.simpleBay }; numberOfBayDesigns = 1; } //start with first window width - we'll be adding to this until we have filled the facade width int it = 100; while (true) { int patternModIndex = numberOfBays % numberOfBayDesigns; float patternAddition = bays[patternModIndex].openingWidth + bays[patternModIndex].minimumBayWidth; if (patternSize + patternAddition < facadeWidth) { patternSize += patternAddition; numberOfBays++; } else break; it--; if (it < 0) break; } float perBayAdditionalSpacing = (facadeWidth - patternSize) / numberOfBays; float windowXBase = 0; for (int c = 0; c < numberOfBays; c++) { BuildrBay bayStyle; if (facadeDesign.type == BuildrFacadeDesign.types.patterned) { int numberOfBayStyles = facadeDesign.bayPattern.Count; bayStyle = bays[c % numberOfBayStyles]; } else { bayStyle = facadeDesign.simpleBay; } float actualWindowSpacing = bayStyle.minimumBayWidth + perBayAdditionalSpacing; float leftSpace = actualWindowSpacing * bayStyle.openingWidthRatio; float rightSpace = actualWindowSpacing - leftSpace; float openingSpace = bayStyle.openingWidth; Vector3 bayDimensions; int subMesh; bool flipped; if (!bayStyle.isOpening) { subMesh = bayStyle.GetTexture(BuildrBay.TextureNames.WallTexture); flipped = bayStyle.IsFlipped(BuildrBay.TextureNames.WallTexture); bayBase.x = windowXBase; bayBase.y = currentFloorBase; float bayWidth = (openingSpace + actualWindowSpacing); float bayHeight = floorHeight; bayDimensions = new Vector2(bayWidth, bayHeight); DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition); windowXBase += bayWidth;//move base vertor to next bay continue;//bay filled - move onto next bay } float rowBottomHeight = ((floorHeight - bayStyle.openingHeight) * bayStyle.openingHeightRatio); float rowTopHeight = (floorHeight - rowBottomHeight - bayStyle.openingHeight); //Window subMesh = bayStyle.GetTexture(BuildrBay.TextureNames.OpeningBackTexture); flipped = bayStyle.IsFlipped(BuildrBay.TextureNames.OpeningBackTexture); bayBase.x = windowXBase + leftSpace; bayBase.y = currentFloorBase + rowBottomHeight; bayDimensions = new Vector2(bayStyle.openingWidth, bayStyle.openingHeight); DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition); //Column Left if (leftSpace > 0) { subMesh = bayStyle.GetTexture(BuildrBay.TextureNames.ColumnTexture); flipped = bayStyle.IsFlipped(BuildrBay.TextureNames.ColumnTexture); bayBase.x = windowXBase; bayBase.y = currentFloorBase + rowBottomHeight; bayDimensions = new Vector2(leftSpace, bayStyle.openingHeight); DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition); } //Column Right if (rightSpace > 0) { subMesh = bayStyle.GetTexture(BuildrBay.TextureNames.ColumnTexture); flipped = bayStyle.IsFlipped(BuildrBay.TextureNames.ColumnTexture); bayBase.x = windowXBase + leftSpace + openingSpace; bayBase.y = currentFloorBase + rowBottomHeight; bayDimensions = new Vector2(rightSpace, bayStyle.openingHeight); DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition); } //Row Bottom if (rowBottomHeight > 0) { subMesh = bayStyle.GetTexture(BuildrBay.TextureNames.RowTexture); flipped = bayStyle.IsFlipped(BuildrBay.TextureNames.RowTexture); bayBase.x = windowXBase + leftSpace; bayBase.y = currentFloorBase; bayDimensions = new Vector2(openingSpace, rowBottomHeight); DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition); } //Row Top if (rowTopHeight > 0) { subMesh = bayStyle.GetTexture(BuildrBay.TextureNames.RowTexture); flipped = bayStyle.IsFlipped(BuildrBay.TextureNames.RowTexture); bayBase.x = windowXBase + leftSpace; bayBase.y = currentFloorBase + rowBottomHeight + bayStyle.openingHeight; bayDimensions = new Vector2(openingSpace, rowTopHeight); DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition); } //Cross Left if (leftSpace > 0) { //Cross Left Bottom subMesh = bayStyle.GetTexture(BuildrBay.TextureNames.CrossTexture); flipped = bayStyle.IsFlipped(BuildrBay.TextureNames.CrossTexture); bayBase.x = windowXBase; bayBase.y = currentFloorBase; bayDimensions = new Vector2(leftSpace, rowBottomHeight); DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition); //Cross Left Top subMesh = bayStyle.GetTexture(BuildrBay.TextureNames.CrossTexture); flipped = bayStyle.IsFlipped(BuildrBay.TextureNames.CrossTexture); bayBase.x = windowXBase; bayBase.y = currentFloorBase + rowBottomHeight + bayStyle.openingHeight; bayDimensions = new Vector2(leftSpace, rowTopHeight); DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition); } //Cross Right if (rightSpace > 0) { //Cross Left Bottom subMesh = bayStyle.GetTexture(BuildrBay.TextureNames.CrossTexture); flipped = bayStyle.IsFlipped(BuildrBay.TextureNames.CrossTexture); bayBase.x = windowXBase + leftSpace + openingSpace; bayBase.y = currentFloorBase; bayDimensions = new Vector2(rightSpace, rowBottomHeight); DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition); //Cross Left Top subMesh = bayStyle.GetTexture(BuildrBay.TextureNames.CrossTexture); flipped = bayStyle.IsFlipped(BuildrBay.TextureNames.CrossTexture); bayBase.x = windowXBase + leftSpace + openingSpace; bayBase.y = currentFloorBase + rowBottomHeight + bayStyle.openingHeight; bayDimensions = new Vector2(rightSpace, rowTopHeight); DrawFacadeTexture(sourceTextures, bayBase, bayDimensions, subMesh, flipped, packedPosition); } windowXBase += leftSpace + openingSpace + rightSpace;//move base vertor to next bay } } else { // windowless wall int subMesh = facadeDesign.simpleBay.GetTexture(BuildrBay.TextureNames.WallTexture); bool flipped = facadeDesign.simpleBay.IsFlipped(BuildrBay.TextureNames.WallTexture); bayBase.x = 0; bayBase.y = currentFloorBase; Vector2 dimensions = new Vector2(facadeWidth, floorHeight); DrawFacadeTexture(sourceTextures, bayBase, dimensions, subMesh, flipped, packedPosition); } } facadeNumber++; } } //add roof textures int numberOfroofTextures = roofTextures.Count; int scaledPadding = Mathf.FloorToInt(ATLAS_PADDING * packedScale); for (int i = 0; i < numberOfroofTextures; i++) { Rect roofTexturePosition = packedTexturePositions[i + facadeNumber]; BuildrTexture bTexture = roofTextures[i]; int roofTextureWidth = bTexture.texture.width; int roofTextureHeight = bTexture.texture.height; int targetTextureWidth = Mathf.RoundToInt(roofTexturePosition.width); int targetTextureHeight = Mathf.RoundToInt(roofTexturePosition.height); if (bTexture.maxUVTile == Vector2.zero) continue; int sourceTextureWidth = Mathf.RoundToInt(targetTextureWidth / (bTexture.tiled ? bTexture.maxUVTile.x : bTexture.tiledX)); int sourceTextureHeight = Mathf.RoundToInt(targetTextureHeight / (bTexture.tiled ? bTexture.maxUVTile.y : bTexture.tiledY)); int sourceTextureSize = sourceTextureWidth * sourceTextureHeight; if (sourceTextureSize == 0) { //Debug.Log(sourceTextureWidth+" "+sourceTextureHeight+" "+bTexture.tiledX+" "+bTexture.maxUVTile+" "+bTexture.tiledX+","+bTexture.tiledY); continue; } Color32[] roofColourArray = TextureScale.NearestNeighbourSample(((Texture2D)bTexture.texture).GetPixels32(), roofTextureWidth, roofTextureHeight, sourceTextureWidth, sourceTextureHeight); //Color32[] roofColourArray = bTexture.texture.GetPixels32(); for (int x = 0; x < targetTextureWidth; x++) { for (int y = 0; y < targetTextureHeight; y++) { int drawX = Mathf.FloorToInt(x + roofTexturePosition.x); int drawY = Mathf.FloorToInt(y + roofTexturePosition.y); int colourIndex = drawX + drawY * textureWidth; int sx = x % sourceTextureWidth; int sy = y % sourceTextureHeight; int sourceIndex = sx + sy * sourceTextureWidth; if (sourceIndex >= sourceTextureSize) Debug.Log("Source Index too big " + sx + " " + sy + " " + sourceTextureWidth + " " + sourceTextureSize + " " + bTexture.maxUVTile + " " + bTexture.name); Color32 sourceColour = roofColourArray[sourceIndex]; if (colourIndex >= textureSize) Debug.Log("Output Index Too big " + drawX + " " + drawY + " " + colourIndex + " " + textureSize + " " + roofTexturePosition); colourArray[colourIndex] = sourceColour; //Padding if (x == 0) { for (int p = 0; p < scaledPadding; p++) { colourArray[colourIndex - p] = sourceColour; } } if (x == targetTextureWidth - 1) { for (int p = 0; p < scaledPadding; p++) { colourArray[colourIndex + p] = sourceColour; } } if (y == 0) { for (int p = 0; p < scaledPadding; p++) { colourArray[colourIndex - (p * textureWidth)] = sourceColour; } } if (y == targetTextureHeight - 1) { for (int p = 0; p < scaledPadding; p++) { colourArray[colourIndex + (p * textureWidth)] = sourceColour; } } } } } }