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); bool handness = spline.Handness(pixelPos) >= 0; dstMatrix.PaintBucket(new Coord(x, z), handness ? 0.75f : 0.25f); } } } }
public static void DrawKnob(SplineSys sys, int l, int n) { using (Cell.LineStd) Draw.DualLabel("Number", "Line:" + l.ToString() + ", Node:" + n.ToString()); using (Cell.LineStd) Draw.Toggle(n == 0, "Is First"); using (Cell.LineStd) Draw.Toggle(n == sys.lines[l].segments.Length, "Is Last"); SplineEditor.Knob knob = sys.lines[l].GetKnob(n); using (Cell.LinePx(0)) { using (Cell.LineStd) Draw.Field(ref knob.pos, "Position"); //using (Cell.LineStd) Draw.DualLabel("In Dir", knob.inDir.ToString()); //using (Cell.LineStd) Draw.DualLabel("Out Dir", knob.outDir.ToString()); using (Cell.LineStd) Draw.Field(ref knob.inDir, "In Dir"); using (Cell.LineStd) Draw.Field(ref knob.outDir, "Out Dir"); using (Cell.LineStd) Draw.Field(ref knob.type, "Type"); if (Cell.current.valChanged) { sys.lines[l].SetKnob(knob, n); sys.lines[l].Update(); SceneView.lastActiveSceneView?.Repaint(); } } }
public static SplineSys CreateDefault() { SplineSys spline = new SplineSys(); spline.lines = new Line[] { new Line() }; spline.lines[0].segments = new Segment[] { new Segment(new Vector3(0, 0, 0), new Vector3(1, 0, 0)) }; return(spline); }
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 SplineSys(SplineSys src) { CopyLinesFrom(src.lines); guiDrawNodes = src.guiDrawNodes; guiDrawSegments = src.guiDrawSegments; guiDrawDots = src.guiDrawDots; guiDotsCount = src.guiDotsCount; guiDotsEquidist = src.guiDotsEquidist; }
public static void Stroke(SplineSys 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) { foreach (Line line in spline.lines) { for (int s = 0; s < line.segments.Length; s++) { int numSteps = (int)(line.segments[s].length / matrix.PixelSize.x * 0.1f + 1); Vector3 startPos = line.segments[s].start.pos; Vector3 prevCoord = matrix.WorldToPixelInterpolated(startPos.x, startPos.z); float prevHeight = white ? intensity : (startPos.y / matrix.worldSize.y); for (int i = 0; i < numSteps; i++) { float percent = numSteps != 1 ? 1f * i / (numSteps - 1) : 1; Vector3 pos = line.segments[s].GetPoint(percent); 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: i == numSteps - 1); prevCoord = pos; prevHeight = posHeight; } } } }
/*UI ui = new UI(); * SplineObject so; * * public void OnSceneGUI () * { * if (so == null) so = (SplineObject)target; * ui.DrawInspector(() => DrawSpline(so.splineSys)); * }*/ public static void DrawSpline(SplineSys sys) { using (Cell.LineStd) using (new Draw.FoldoutGroup(ref guiDisplay, "Display", isLeft: true)) if (guiDisplay) { using (Cell.LineStd) Draw.ToggleLeft(ref sys.guiDrawNodes, "Draw Nodes"); using (Cell.LineStd) Draw.ToggleLeft(ref sys.guiDrawSegments, "Draw Segments"); using (Cell.LineStd) Draw.ToggleLeft(ref sys.guiDrawDots, "Draw Dots"); using (Cell.LineStd) Draw.Field(ref sys.guiDotsCount, "Dots Count"); using (Cell.LineStd) Draw.Toggle(ref sys.guiDotsEquidist, "Dots Equidist"); if (Cell.current.valChanged) { SceneView.lastActiveSceneView?.Repaint(); } } Cell.EmptyLinePx(4); using (Cell.LineStd) using (new Draw.FoldoutGroup(ref guiLines, "Lines", isLeft: true)) if (guiLines) { using (Cell.LineStd) Draw.DualLabel("Lines Count", sys.lines.Length.ToString()); if (SplineEditor.selectedKnobs.Count == 1) { (int l, int n) = SplineEditor.selectedKnobs.Any(); Line line = sys.lines[l]; using (Cell.LineStd) Draw.DualLabel("Length", line.length.ToString()); using (Cell.LineStd) Draw.DualLabel("Segments", line.segments.Length.ToString()); using (Cell.LineStd) Draw.Toggle(ref line.looped, "Looped"); using (Cell.LineStd) if (Draw.Button("Remove")) { sys.RemoveLine(l); SplineEditor.selectedKnobs.Clear(); SplineEditor.dispSelectedKnobs.Clear(); } } using (Cell.LineStd) if (Draw.Button("Add")) { sys.AddLine( SceneView.lastActiveSceneView.pivot - new Vector3(SceneView.lastActiveSceneView.cameraDistance / 10, 0, 0), SceneView.lastActiveSceneView.pivot + new Vector3(SceneView.lastActiveSceneView.cameraDistance / 10, 0, 0)); } } Cell.EmptyLinePx(4); using (Cell.LineStd) using (new Draw.FoldoutGroup(ref guiKnobs, "Knobs", isLeft: true)) if (guiKnobs) { using (Cell.LineStd) Draw.DualLabel("Selected", SplineEditor.selectedKnobs.Count.ToString()); if (SplineEditor.selectedKnobs.Count == 1) { Cell.EmptyLinePx(4); (int l, int n) = SplineEditor.selectedKnobs.Any(); using (Cell.LinePx(0)) DrawKnob(sys, l, n); } } Cell.EmptyLinePx(4); using (Cell.LineStd) if (Draw.Button("Update")) { sys.Update(); SceneView.lastActiveSceneView?.Repaint(); } }