////////////////////////////////
// WPF+SkiaSharp ワイヤーフレーム
////////////////////////////////
using SkiaSharp;
using SkiaSharp.Views.Desktop;
using SkiaSharp.Views.WPF;
using System;
using System.Windows;
using System.Windows.Threading;
namespace WireframeWpf{
public partial class MainWindow : Window{
private SKPoint3[] vertices;
private (int, int)[] edges;
private float angle = 0;
public MainWindow() {
InitializeComponent();
vertices = new SKPoint3[]{
new SKPoint3(-1, -1, -1),
new SKPoint3(1, -1, -1),
new SKPoint3(1, 1, -1),
new SKPoint3(-1, 1, -1),
new SKPoint3(-1, -1, 1),
new SKPoint3(1, -1, 1),
new SKPoint3(1, 1, 1),
new SKPoint3(-1, 1, 1)
};
edges = new (int, int)[] {
(0,1),(1,2),(2,3),(3,0),
(4,5),(5,6),(6,7),(7,4),
(0,4),(1,5),(2,6),(3,7)
};
var timer = new DispatcherTimer {
Interval = TimeSpan.FromMilliseconds(2)
};
timer.Tick += (s, e) => {
angle += 0.01f;
SkElement.InvalidateVisual();
};
timer.Start();
}
private SKPoint3 RotateY(SKPoint3 p, float angle) {
float cosA = (float)Math.Cos(angle);
float sinA = (float)Math.Sin(angle);
return new SKPoint3(
p.X * cosA - p.Z * sinA,
p.Y,
p.X * sinA + p.Z * cosA
);
}
private SKPoint Project(SKPoint3 p, float width, float height, float fov, float viewerDistance) {
float factor = fov / (viewerDistance + p.Z);
float x = p.X * factor + width / 2;
float y = -p.Y * factor + height / 2;
return new SKPoint(x, y);
}
private void SkElement_PaintSurface(object sender, SKPaintSurfaceEventArgs e){
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.Black);
SKPoint3[] rotated = new SKPoint3[vertices.Length];
for (int i = 0; i < vertices.Length; i++){
rotated[i] = RotateY(vertices[i], angle);
}
var paint = new SKPaint {
Color = SKColors.Blue,
StrokeWidth = 3,
IsStroke = true,
IsAntialias = true
};
foreach (var (start, end) in edges){
var p1 = Project(rotated[start], info.Width, info.Height, 256, 3);
var p2 = Project(rotated[end], info.Width, info.Height, 256, 3);
canvas.DrawLine(p1, p2, paint);
}
}
}
}