1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CG Library SkiaSharp「3Dアニメーション」

Last updated at Posted at 2023-11-11
・~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~・
・グラフィックスライブラリ、SkiaSharpのSKMatrix44クラスを使用し、
・非アフェン変換を行い立体化させパラメータを連続可変させてアニメーション化します。
・~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~・

1.マーク・フリント氏による伝説のOP(83年)の再現のスクリーンショット 40年ぶりに蘇る
B.jpg
2.WQHD(2540x1440)での動画(キャプチャ中でFPS下がってます)。他、10年前のノートPCでもそれなりに動きました。

  • 作ってて結局わからず放置してたがサンプルを見つけそれを改変しました。
  • SKMatrixが古い等と警告でますがメークは通ります。
  • 手製のプログラムに内蔵して演出させたらどうでしょう。パラメータ変えると色々表示が変わります。
  • 元来、2D専用と言う事もあり厚みがありません。
  • その昔、x86でグラフィックディスプレイコントローラ(μPD7220)直叩きで3Dやってたのに今や高級言語で出来ちゃう時代。

1.XYZ軸回転しながら近づいてまた遠方へ

漢字用 LINEフォント入れてない場合はTypeface = SKTypeface.FromFamilyName("LINE Seed JP_OTF"), を削除。

// SkiaSharp Test / inf102
// https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/transforms/3d-rotation

using SkiaSharp;
using SkiaSharp.Views.Desktop;
using System;
using System.Threading.Tasks;
using System.Windows;

namespace SkiaSharpSample {

    public partial class MainWindow : Window	{

        static int r=0;//2000;
        static float s=0;//=23;
        static bool flg;
        static string[] st = {   "SKIA SHARP&SKMatrix44","三次元アニメーション映像", "3D VALIANT", "ThreeDimensions","Smooth 3D Video" };
        static int stn = 0;

		public MainWindow()		{
			InitializeComponent();
            this.WindowState = WindowState.Maximized;
		}

        private async  void Window_Loaded(object sender, RoutedEventArgs e) {

            while (true){
                skiaCanvas2.InvalidateVisual(); 

               // Title = r + "s="+s;

                if (r == 632)  stn = 1;
                if (r == 1345) stn = 2;
                if (r == 2427) stn = 3; 
                if (r == 2249 && flg == true) stn = 4;
                                
                if (r>=3000) {
                    flg =true;
                }

                if (r<=0 || s<=0 ) {
                    flg=false;
                    r=0;
                }

                // 大きく
                if (flg == false) {
               
                    r++;
                    s=s+(float)0.01; // SIZE
                }
                // 小さくする
                else {
                 
                    r--;
                    s=s-(float)0.03;
                }

                await Task.Delay (1); //2000 23
                 
            }
        }


		void PaintSurface(object sender, SKPaintSurfaceEventArgs args){

            SKImageInfo info = args.Info;
            SKSurface surface = args.Surface;
            SKCanvas canvas = surface.Canvas;

            canvas.Clear(SKColors.Black);

            SKPaint textPaint = new SKPaint{
                Style = SKPaintStyle.Fill,
                Color = SKColors.Yellow,
                IsAntialias=true,
                LcdRenderText=true,
                FakeBoldText = true,
                TextSize = s,
                TextAlign= (SKTextAlign)SKTextAlign.Center,
                Typeface = SKTypeface.FromFamilyName("LINE Seed JP_OTF"),
                //TextSkewX=2, // 斜め
                //TextScaleX = 3f // 圧縮
            };

            if(stn == 1) textPaint.Color = new SKColor(0, 255, 0);
            if(stn == 2) textPaint.Color = new SKColor(0, 00, 255);

            // 色を変える場合
            Random Rnd = new Random();
            if (flg) textPaint.Color=new SKColor((byte)Rnd.Next(0, 255), (byte)Rnd.Next(0, 255),(byte)Rnd.Next(0, 255));

            // Find center of canvas
            float xCenter = info.Width / 2;
            float yCenter = info.Height / 2;

            // Translate center to origin
            SKMatrix matrix = SKMatrix.MakeTranslation(-xCenter, -yCenter);

            // Scale so text fits
            float scale = Math.Min(info.Width / 110,info.Height / 110);
            SKMatrix.PostConcat(ref matrix, SKMatrix.MakeScale(scale, scale));

            // Calculate composite 3D transforms
            float depth = 0.75f * scale * 100;
        
            SKMatrix44 matrix44 = SKMatrix44.CreateIdentity();
            matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(1, 0, 0, (float)r));   // 上下回転
            matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(0, 1, 0, (float)r));   // 左右回転
            matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(0, 0, 1, (float)r));   // 時計風回転

            SKMatrix44 perspectiveMatrix = SKMatrix44.CreateIdentity();
            perspectiveMatrix[3, 2] = -1 / depth;
            matrix44.PostConcat(perspectiveMatrix);

            // Concatenate with 2D matrix
            SKMatrix.PostConcat(ref matrix, matrix44.Matrix);

            // Translate back to center
            SKMatrix.PostConcat(ref matrix,SKMatrix.MakeTranslation(xCenter, yCenter));

            // Set the matrix and display the text 縦横移動率
            canvas.SetMatrix(matrix);
            float xText = xCenter - 3;
            float yText = yCenter + 5;

            canvas.DrawText(st[stn], xText, yText, textPaint);

        }

	}
}

2.Y軸のみ回転

// SkiaSharp Test / Y軸回転
// https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/transforms/3d-rotation

using SkiaSharp;
using SkiaSharp.Views.Desktop;
using System;
using System.Threading.Tasks;
using System.Windows;

namespace SkiaSharpSample {

    public partial class MainWindow : Window	{

        static int r=0;
        static float s=2;
        static bool flg=false;
        static string text="";

		public MainWindow()		{
			InitializeComponent();
            this.WindowState = WindowState.Maximized;
		}

        private async  void Window_Loaded(object sender, RoutedEventArgs e) {

            // 1st
            text="3D VALIANT";

            while (true){
                skiaCanvas2.InvalidateVisual();

                Title = s.ToString();

                if (  s>=(float)30.06483  && flg==false) {
                    s=14;
                    r=0;
                    flg=true;
                    text="WPF+SkiaSharp"; //2nd
                }

                r++; // 回転
                s=s+(float)0.015; // SIZE
                
                await Task.Delay(1); 
                 
            }
        }


		void PaintSurface(object sender, SKPaintSurfaceEventArgs args){

            SKImageInfo info = args.Info;
            SKSurface surface = args.Surface;
            SKCanvas canvas = surface.Canvas;

            canvas.Clear(SKColors.Black);

            SKPaint textPaint = new SKPaint{
                Style = SKPaintStyle.Fill,
                IsAntialias=true,
                LcdRenderText=true,
                TextSize = s,
       
                TextAlign= (SKTextAlign)SKTextAlign.Center,
           
                //    Typeface = SKTypeface.FromFamilyName("LINE Seed JP_OTF"),
  
            };

            if(flg == false) textPaint.Color = new SKColor(0, 255,127);
            else textPaint.Color = new SKColor(255, 218,185);

            // 色を変える場合
            Random Rnd = new Random();
          //  textPaint.Color=new SKColor((byte)Rnd.Next(0, 255), (byte)Rnd.Next(0, 255),(byte)Rnd.Next(0, 255));

            // Find center of canvas
            float xCenter = info.Width / 2;
            float yCenter = info.Height / 2;

            // Translate center to origin
            SKMatrix matrix = SKMatrix.MakeTranslation(-xCenter, -yCenter);

            // Scale so text fits
            float scale = Math.Min(info.Width / 110,info.Height / 110);
            SKMatrix.PostConcat(ref matrix, SKMatrix.MakeScale(scale, scale));

            // Calculate composite 3D transforms
            float depth = 0.75f * scale * 100;
            SKMatrix44 matrix44 = SKMatrix44.CreateIdentity();
            matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(0, 1, 0, (float)r));   
          //  if (flg==true){
             //   matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(0, 0, 1, (float)r));   
           //     matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(1, 0, 0, (float)r));
          //  }

            SKMatrix44 perspectiveMatrix = SKMatrix44.CreateIdentity();
            perspectiveMatrix[3, 2] = -1 / depth;
            matrix44.PostConcat(perspectiveMatrix);

            // Concatenate with 2D matrix
            SKMatrix.PostConcat(ref matrix, matrix44.Matrix);

            // Translate back to center
            SKMatrix.PostConcat(ref matrix,SKMatrix.MakeTranslation(xCenter, yCenter));

            // Set the matrix and display the text
            canvas.SetMatrix(matrix);
            float xText = xCenter - 0;  //回転軸
            float yText = yCenter + 9;  //縦位置

            canvas.DrawText(text, xText, yText+1, textPaint);
  
        }
	}
}

3.XAML (共通)

<Window x:Class="SkiaSharpSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:SkiaSharpSample" xmlns:skia="clr-namespace:SkiaSharp.Views.WPF;assembly=SkiaSharp.Views.WPF" 
        xmlns:wpf="clr-namespace:SkiaSharp.Views.WPF;assembly=SkiaSharp.Views.WPF" mc:Ignorable="d"
        Title="SkiaSharp" Loaded="Window_Loaded" Height="850" Width="850" >

    <Grid  >

        <wpf:SKElement x:Name="skiaCanvas2" PaintSurface="PaintSurface"  />
    </Grid>

</Window>
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?