public static void Mask(TransitionsList src, TransitionsList dst, MatrixWorld mask, Noise random, bool invert) /// Adds masked (or unmasked if invert) objects to dst { for (int t = 0; t < src.count; t++) { Vector3 pos = src.arr[t].pos; if (pos.x <= mask.worldPos.x && pos.x >= mask.worldPos.x + mask.worldSize.x && pos.z <= mask.worldPos.z && pos.z >= mask.worldPos.x + mask.worldSize.z) { continue; //do remove out of range objects? } float val = mask.GetWorldValue(pos.x, pos.z); float rnd = random.Random(src.arr[t].hash); if (val < rnd && invert) { dst.Add(src.arr[t]); } if (val >= rnd && !invert) { dst.Add(src.arr[t]); } } }
public static bool SkipOnBiome (ref Transition trs, BiomeBlend biomeBlend, MatrixWorld biomeMask, Noise random) /// True if object should not be spawned because of biome mask /// ref since it can change scale { float biomeFactor = biomeMask!=null ? biomeMask.GetWorldInterpolatedValue(trs.pos.x, trs.pos.z) : 1; if (biomeFactor < 0.00001f) return true; bool skip; switch (biomeBlend) { case BiomeBlend.Sharp: skip = biomeFactor < 0.5f; break; case BiomeBlend.Random: float rnd = random.Random((int)trs.pos.x, (int)trs.pos.y); //TODO: use id? if (biomeFactor > 0.5f) rnd = 1-rnd; skip = biomeFactor < rnd; break; case BiomeBlend.Scale: trs.scale *= biomeFactor; skip = biomeFactor < 0.0001f; break; case BiomeBlend.Pure: skip = biomeFactor < 0.9999f; break; default: skip = false; break; } return skip; }
public static void Silhouette(SplineSys spline, MatrixWorld strokeMatrix, MatrixWorld dstMatrix) /// Fills all pixels within closed spline with 1, and all outer pixels with 0 /// Pixels directly in the spline are filled with 0.5 /// Requires the matrix with line stroked. StrokeMatrix and DstMatrix could be the same { if (strokeMatrix != dstMatrix) { dstMatrix.Fill(strokeMatrix); } //and then using dst matrix only CoordRect rect = dstMatrix.rect; Coord min = rect.Min; Coord max = rect.Max; for (int x = min.x; x < max.x; x++) { for (int z = min.z; z < max.z; z++) { int pos = (z - rect.offset.z) * rect.size.x + x - rect.offset.x; if (dstMatrix.arr[pos] < 0.01f) //free from stroke and fill { Vector3 pixelPos = dstMatrix.PixelToWorld(x, z, center: true); bool handness = spline.Handness(pixelPos) >= 0; dstMatrix.PaintBucket(new Coord(x, z), handness ? 0.75f : 0.25f); } } } }
public void ProcessToFloor(Inlet <SplineSys> splineIn, Outlet <SplineSys> splineOut, TileData data, StopToken stop) { SplineSys src = data.ReadInletProduct(splineIn); MatrixWorld heights = data.ReadInletProduct(heightIn); if (src == null) { return; } if (!enabled || heights == null) { data.StoreProduct(splineOut, src); return; } if (stop != null && stop.stop) { return; } SplineSys dst = new SplineSys(src); FloorSplines(dst, heights); dst.Update(); if (stop != null && stop.stop) { return; } data.StoreProduct(splineOut, dst); DebugGizmos.Clear("Spline"); foreach (Segment segment in dst.lines[0].segments) { DebugGizmos.DrawLine("Spline", segment.start.pos, segment.end.pos, Color.white, additive: true); } }
public object Read(CoordRect worldRect, float worldHeight, CoordRect pixelRect) { MatrixWorld matrix = new MatrixWorld(pixelRect, worldRect.offset.vector2d, worldRect.size.vector2d, worldHeight); matrix.ImportData(terrain.terrainData, channel); return(matrix); }
public static void Floor(MatrixWorld heights, Spline spline, bool interpolated = true) /// Drops spline to height matrix { for (int n = 0; n < spline.nodes.Length; n++) { Vector3 node = spline.nodes[n]; if (node.x <= heights.worldPos.x) { node.x = heights.worldPos.x + 0.001f; } if (node.x >= heights.worldPos.x + heights.worldSize.x) { node.x = heights.worldPos.x + heights.worldSize.x - 0.001f; } if (node.z <= heights.worldPos.z) { node.z = heights.worldPos.z + 0.001f; } if (node.z >= heights.worldPos.z + heights.worldSize.z) { node.z = heights.worldPos.z + heights.worldSize.z - 0.001f; } float height = interpolated ? heights.GetWorldInterpolatedValue(node.x, node.z) : heights.GetWorldValue(node.x, node.z); spline.nodes[n].y = height * heights.worldSize.y; } }
public static void Stroke(Spline spline, MatrixWorld matrix, bool white = false, float intensity = 1, bool antialiased = false, bool padOnePixel = false) /// Draws a line on matrix /// White will fill the line with 1, when disabled it will use spline height /// PaddedOnePixel works similarly to AA, but fills border pixels with full value (to create main tex for the mask) { Vector3 startPos = spline.nodes[0]; Vector3 prevCoord = matrix.WorldToPixelInterpolated(startPos.x, startPos.z); float prevHeight = white ? intensity : (startPos.y / matrix.worldSize.y); for (int n = 0; n < spline.nodes.Length; n++) { Vector3 pos = spline.nodes[n]; float posHeight = white ? intensity : (pos.y / matrix.worldSize.y); pos = matrix.WorldToPixelInterpolated(pos.x, pos.z); matrix.Line( new Vector2(prevCoord.x, prevCoord.z), new Vector2(pos.x, pos.z), prevHeight, posHeight, antialised: antialiased, paddedOnePixel: padOnePixel, endInclusive: n == spline.nodes.Length - 1); prevCoord = pos; prevHeight = posHeight; } }
public static void Silhouette(SplineSys spline, MatrixWorld matrix, bool strokePrepared = false) /// Fills all pixels within closed spline with 1, and all outer pixels with 0 /// Pixels directly in the spline are filled with 0.5 /// Requires an empty matrix (can use matrix with the stroke, in this case strokePrepared should be set to true) { if (!strokePrepared) { Stroke(spline, matrix, white: true, intensity: 0.5f, antialiased: false, padOnePixel: false); } CoordRect rect = matrix.rect; Coord min = rect.Min; Coord max = rect.Max; for (int x = min.x; x < max.x; x++) { for (int z = min.z; z < max.z; z++) { int pos = (z - rect.offset.z) * rect.size.x + x - rect.offset.x; if (matrix.arr[pos] < 0.01f) //free from stroke and fill { Vector3 pixelPos = matrix.PixelToWorld(x, z, center: true); bool handness = spline.Handness(pixelPos) >= 0; matrix.PaintBucket(new Coord(x, z), handness ? 0.75f : 0.25f); } } } }
public static void Silhouette(Spline[] splines, MatrixWorld strokeMatrix, MatrixWorld dstMatrix) /// Fills all pixels within closed spline with 1, and all outer pixels with 0 /// Pixels directly in the spline are filled with 0.5 /// Requires the matrix with line stroked. StrokeMatrix and DstMatrix could be the same { DebugGizmos.Clear("Slhuette"); if (strokeMatrix != dstMatrix) { dstMatrix.Fill(strokeMatrix); } //and then using dst matrix only CoordRect rect = dstMatrix.rect; Coord min = rect.Min; Coord max = rect.Max; for (int x = min.x; x < max.x; x++) { for (int z = min.z; z < max.z; z++) { int pos = (z - rect.offset.z) * rect.size.x + x - rect.offset.x; if (dstMatrix.arr[pos] < 0.01f) //free from stroke and fill { Vector2D pixelPos = (Vector2D)dstMatrix.PixelToWorld(x, z); bool handness = Spline.Handness(splines, pixelPos) >= 0; DebugGizmos.DrawDot("Slhuette", (Vector3)pixelPos, 6, color: handness ? Color.red : Color.green, additive: true); dstMatrix.PaintBucket(new Coord(x, z), handness ? 0.75f : 0.25f); } } } }
public static void PaintBucket(this MatrixWorld matrix, Coord coord, float val, float threshold = 0.0001f, int maxIterations = 10) /// Like a paintBucket tool in photoshop /// Fills all zero (lower than threshold) values with val, until meets borders /// Doesnt guarantee filling (areas after the corner could be missed) /// Use threshold to change between mask -1 or 0 /// TODO: to matrix ops { CoordRect rect = matrix.rect; Coord min = rect.Min; Coord max = rect.Max; MatrixOps.Stripe stripe = new MatrixOps.Stripe(Mathf.Max(rect.size.x, rect.size.z)); stripe.length = rect.size.x; matrix[coord] = -256; //starting mask //first vertical spread is one row-only MatrixOps.ReadRow(stripe, matrix, coord.x, matrix.rect.offset.z); PaintBucketMaskStripe(stripe, threshold); MatrixOps.WriteRow(stripe, matrix, coord.x, matrix.rect.offset.z); for (int i = 0; i < maxIterations; i++) //ten tries, but hope it will end before that { bool change = false; //horizontally for (int z = min.z; z < max.z; z++) { MatrixOps.ReadLine(stripe, matrix, rect.offset.x, z); change = PaintBucketMaskStripe(stripe, threshold) || change; MatrixOps.WriteLine(stripe, matrix, rect.offset.x, z); } //vertically for (int x = min.x; x < max.x; x++) { MatrixOps.ReadRow(stripe, matrix, x, matrix.rect.offset.z); change = PaintBucketMaskStripe(stripe, threshold) || change; MatrixOps.WriteRow(stripe, matrix, x, matrix.rect.offset.z); } if (!change) { break; } //if (i==maxIterations-1 && !change) // Debug.Log("Reached max iterations"); } //filling masked values with val for (int i = 0; i < matrix.arr.Length; i++) { if (matrix.arr[i] < -255) { matrix.arr[i] = val; } } }
public static void Silhouette(SplineSys spline, MatrixWorld matrix) /// Fills all pixels within closed spline with 1, and all outer pixels with 0 /// Pixels directly in the spline are filled with 0.5 /// Internally strokes matrix first { Stroke(spline, matrix, white: true, intensity: 0.5f, antialiased: false, padOnePixel: false); Silhouette(spline, matrix, matrix); }
public void SetBiomeMask(MatrixWorld mask, MatrixWorld parentBiomeMask) { currentBiomeMask = new MatrixWorld(mask); //setting a copy since generate will compare with previously applied one if (parentBiomeMask != null) { currentBiomeMask.Multiply(parentBiomeMask); } }
public object Read(CoordRect worldRect, float worldHeight, CoordRect pixelRect) { MatrixWorld matrix = new MatrixWorld(pixelRect, worldRect.offset.vector2d, worldRect.size.vector2d, worldHeight); float[,] arr2D = terrain.terrainData.GetHeights(0, 0, terrain.terrainData.heightmapResolution, terrain.terrainData.heightmapResolution); matrix.ImportHeights(arr2D); return(matrix); }
private void createStage() { for (int i = 0; i < MatrixWorld.Count(); i++) { Floor.Draw(MatrixWorld[i], Camera.View, Camera.Projection); } // worldMatrix=generarCubosRectos(4); // Floor.draw(); }
public TileData(TileData src) { area = src.area; globals = src.globals; isPreview = src.isPreview; isDraft = src.isDraft; random = src.random; currentBiomeMask = src.currentBiomeMask; }
public void SetObject(MatrixWorld matrix, Area area) { this.matrix = matrix; this.activeRect = area.active.rect; this.margins = area.Margins; Stage = PreviewStage.Generating; ThreadManager.Enqueue(ExecuteInThread, priority: -1000); }
public void SetObject(TransitionsList posTab, MatrixWorld heights, Area area) { this.trns = posTab; this.heights = heights; this.worldPos = (Vector3)area.active.worldPos; this.worldSize = (Vector3)area.active.worldSize; Stage = PreviewStage.Generating; ThreadManager.Enqueue(ExecuteInThread, priority: -1000); }
private static Vector3 GetMoveVector(MatrixWorld heights, Vector3 prev, Vector3 node, Vector3 next, float thisWeight, int evalCount, float evalStep, SerpentineFactors factors) { Vector3 tan = (next - prev).normalized; Vector3 perp = Vector3.Cross(tan, Vector3.up); Vector3 minNode = node; float minWeight = thisWeight; float lWeights = 0; float rWeights = 0; float topLeftRating = 0; float topRightRating = 0; for (int p = 1; p <= evalCount; p++) { Vector3 lNode = node + perp * (evalStep * p); lNode.y = heights.GetWorldInterpolatedValue(lNode.x, lNode.z) * heights.worldSize.y; float lRating = GetNodeWeight(prev, lNode, next, factors, heights.worldSize.y); //lWeight = lWeight*(1-(float)p/evalCount) + thisWeight*((float)p/evalCount); lWeights += lRating; if (lRating > topLeftRating) { topLeftRating = lRating; } Vector3 rNode = node - perp * (evalStep * p); rNode.y = heights.GetWorldInterpolatedValue(rNode.x, rNode.z) * heights.worldSize.y; float rRating = GetNodeWeight(prev, rNode, next, factors, heights.worldSize.y); //rWeight = rWeight*(1-(float)p/evalCount) + thisWeight*((float)p/evalCount); rWeights += rRating; if (rRating > topRightRating) { topRightRating = rRating; } } //return perp*(lWeights-rWeights); //return perp*(topLeftWeight-topRightWeight); if (topLeftRating > topRightRating && topLeftRating > thisWeight) { return(perp * (topLeftRating - thisWeight)); } else if (topRightRating > topLeftRating && topRightRating > thisWeight) { return(-perp * (topRightRating - thisWeight)); } else { return(Vector3.zero); } }
public static void FloorSplines(SplineSys dst, MatrixWorld heights) { foreach (Line line in dst.lines) { for (int s = 0; s < line.segments.Length; s++) { line.segments[s].start.pos.y = FloorPoint(line.segments[s].start.pos, heights); } line.segments[line.segments.Length - 1].end.pos.y = FloorPoint(line.segments[line.segments.Length - 1].end.pos, heights); } }
public static void Silhouette(Spline[] splines, MatrixWorld matrix) /// Fills all pixels within closed spline with 1, and all outer pixels with 0 /// Pixels directly in the spline are filled with 0.5 /// Internally strokes matrix first { for (int s = 0; s < splines.Length; s++) { Stroke(splines[s], matrix, white: true, intensity: 0.5f, antialiased: false, padOnePixel: false); } Silhouette(splines, matrix, matrix); }
public static void SpreadOrMultiply(MatrixWorld src, MatrixWorld dst, float range) { float pixelRange = range / src.PixelSize.x; if (pixelRange < 1) //if less than a pixel making line less noticable { dst.Multiply(pixelRange); } else { MatrixOps.SpreadLinear(src, dst, subtract: 1f / pixelRange); } }
public static void Serpentine(MatrixWorld heights, Spline spline, float segLength, int iterations, SerpentineFactors factors) { DebugGizmos.Clear("Serp"); factors.Normalize(); float DistFn(Vector3 n1, Vector3 n2) => Mathf.Sqrt((n1.x - n2.x) * (n1.x - n2.x) + (n1.z - n2.z) * (n1.z - n2.z)); for (int i = 0; i < iterations; i++) { tmpIteration = i; tmpHighlightIteration = iterations - 1; spline.SubdivideDist(segLength, DistFn); Floor(heights, spline); CoordRect rect = heights.rect; Coord rectMin = heights.rect.offset; Coord rectMax = heights.rect.offset + heights.rect.size; float pixelSize = heights.PixelSize.x; Vector3[] newNodes = new Vector3[spline.nodes.Length]; for (int n = 1; n < spline.nodes.Length - 1; n++) { //if (n>2) { newNodes[n]=spline.nodes[n]; continue; } tmpNode = n; float weight = GetNodeWeight(spline.nodes[n - 1], spline.nodes[n], spline.nodes[n + 1], factors, heights.worldSize.y); Vector3 moveVector = GetMoveVector(heights, spline.nodes[n - 1], spline.nodes[n], spline.nodes[n + 1], weight, 1, heights.PixelSize.x, factors); newNodes[n] = spline.nodes[n] + moveVector * 3f; //*heights.PixelSize*0.2f;// * (2f/iterations); if (tmpHighlightIteration == i) { DebugGizmos.DrawRay("Serp", newNodes[n], moveVector, Color.yellow, additive: true); } } newNodes[0] = spline.nodes[0]; newNodes[newNodes.Length - 1] = spline.nodes[spline.nodes.Length - 1]; spline.nodes = newNodes; spline.Weld(segLength / 2, DistFn); } }
public void Clear(bool clearApply = true) /// Clears all of the unnecessary data in playmode { products.Clear(); subDatas.Clear(); prepare.Clear(); ready.Clear(); heights = null; //if (heights != null) heights.Clear(); //clear is faster, but tends to miss an error currentBiomeMask = null; //no Clear since it could be used in other biome finalize.Clear(); if (clearApply) { apply.Clear(); } }
public static void NormalizeLayers(INormalizableLayer[] layers, TileData data, StopToken stop) { //reading products MatrixWorld[] matrices = new MatrixWorld[layers.Length]; float[] opacities = new float[layers.Length]; if (stop != null && stop.stop) { return; } for (int i = 0; i < layers.Length; i++) { if (stop != null && stop.stop) { return; } MatrixWorld srcMatrix = data.products.ReadInlet(layers[i]); if (srcMatrix != null) { matrices[i] = new MatrixWorld(srcMatrix); } //if (matrices[i] != null) // matrices[i].Clamp01(); opacities[i] = layers[i].Opacity; } //normalizing if (stop != null && stop.stop) { return; } matrices.FillNulls(() => new MatrixWorld(data.area.full.rect, (Vector3)data.area.full.worldPos, (Vector3)data.area.full.worldSize)); matrices[0].Fill(1); Matrix.BlendLayers(matrices, opacities); //saving products if (stop != null && stop.stop) { return; } for (int i = 0; i < layers.Length; i++) { data.products[layers[i]] = matrices[i]; } }
public static void SerpentineUnordered(MatrixWorld heights, Spline spline, float segLength, int iterations, SerpentineFactors factors) { DebugGizmos.Clear("Serp"); factors.Normalize(); float DistFn(Vector3 n1, Vector3 n2) => Mathf.Sqrt((n1.x - n2.x) * (n1.x - n2.x) + (n1.z - n2.z) * (n1.z - n2.z)); CoordRect rect = heights.rect; Coord rectMin = heights.rect.offset; Coord rectMax = heights.rect.offset + heights.rect.size; float pixelSize = heights.PixelSize.x; for (int i = 0; i < iterations; i++) { spline.SubdivideDist(segLength, DistFn); Floor(heights, spline); tmpIteration = i; tmpHighlightIteration = iterations - 1; //finding node with lowest rating float lowestRating = float.MaxValue; int lowestNum = 0; for (int n = 1; n < spline.nodes.Length - 1; n++) { float rating = GetNodeWeight(spline.nodes[n - 1], spline.nodes[n], spline.nodes[n + 1], factors, heights.worldSize.y); if (rating < lowestRating) { lowestRating = rating; lowestNum = n; } } tmpNode = lowestNum; float weight = GetNodeWeight(spline.nodes[lowestNum - 1], spline.nodes[lowestNum], spline.nodes[lowestNum + 1], factors, heights.worldSize.y); Vector3 moveVector = GetMoveVector(heights, spline.nodes[lowestNum - 1], spline.nodes[lowestNum], spline.nodes[lowestNum + 1], weight, 1, heights.PixelSize.x, factors); spline.nodes[lowestNum] += moveVector; //*heights.PixelSize*0.2f;// * (2f/iterations); spline.Weld(segLength / 2, DistFn); } }
public void Write(object result) { MatrixWorld matrix = (MatrixWorld)result; matrix.ExportTextureRaw(texture); if (previewInScene) { if (previewObj == null) { CreateSceneObject(); } previewObj.transform.position = matrix.worldPos + matrix.worldSize / 2; previewObj.transform.localScale = new Vector3(matrix.worldSize.x, matrix.worldSize.z, 1); previewMat.SetTexture("_MainTex", texture); } }
public static MatrixWorld Spread(MatrixWorld matrix, float range) { MatrixWorld spreadMatrix; float pixelRange = range / matrix.PixelSize.x; if (pixelRange < 1) //if less than a pixel making line less noticable { spreadMatrix = matrix; spreadMatrix.Multiply(pixelRange); } else //spreading the usual way { spreadMatrix = new MatrixWorld(matrix); MatrixOps.SpreadLinear(matrix, spreadMatrix, subtract: 1f / pixelRange, diagonals: true, quarters: true); } return(spreadMatrix); }
public static Vector3 GetTerrainNormal (float fx, float fz, MatrixWorld heightmap, float heightFactor, float pixelSize) { Coord coord = heightmap.WorldToPixel(fx, fz); int pos = heightmap.rect.GetPos(coord); float curHeight = heightmap.arr[pos]; float prevXHeight = curHeight; if (coord.x>=heightmap.rect.offset.x+1) prevXHeight = heightmap.arr[pos-1]; float nextXHeight = curHeight; if (coord.x<=heightmap.rect.offset.x+heightmap.rect.size.x-1) nextXHeight = heightmap.arr[pos+1]; float prevZHeight = curHeight; if (coord.z>=heightmap.rect.offset.z+1) prevZHeight = heightmap.arr[pos-heightmap.rect.size.x]; float nextZHeight = curHeight; if (coord.z<=heightmap.rect.offset.z+heightmap.rect.size.z-1) nextZHeight = heightmap.arr[pos+heightmap.rect.size.z]; return new Vector3((prevXHeight-nextXHeight)*heightFactor, pixelSize*2, (prevZHeight-nextZHeight)*heightFactor).normalized; }
public static Spline[] Isoline(MatrixWorld matrix, float threshold) { List <MetaLine> metaLines = MatrixToMetaLines(matrix, threshold); List <List <Coord> > lineCoords = WeldMetaLines(metaLines); Spline[] splines = new Spline[lineCoords.Count]; for (int s = 0; s < splines.Length; s++) { Spline spline = new Spline(); List <Coord> coords = lineCoords[s]; splines[s] = spline; spline.nodes = new Vector3[coords.Count]; for (int n = 0; n < spline.nodes.Length; n++) { spline.nodes[n] = matrix.PixelToWorld(coords[n].x - 0.5f, coords[n].z - 0.5f); //-0.5 since it should be between pixels, not in center } } return(splines); }
public object Read(CoordRect worldRect, float worldHeight, CoordRect pixelRect) { CoordRect texRect = new CoordRect(0, 0, texture.width, texture.height); MatrixWorld texMatrix = new MatrixWorld(texRect, worldRect.offset.vector2d, worldRect.size.vector2d, worldHeight); texMatrix.ImportTexture(texture, 0); //resizing if pixel rect differs MatrixWorld testMatrix; if (texMatrix.rect.size != pixelRect.size) { testMatrix = new MatrixWorld(pixelRect, worldRect.offset.vector2d, worldRect.size.vector2d, worldHeight); MatrixOps.Resize(texMatrix, testMatrix); } else { testMatrix = texMatrix; } return(testMatrix); }