日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

WPF中對三維模型的控制

 牛人的尾巴 2016-06-06

WPF中對三維模型的控制

(2012-12-18 19:10:35)
標簽:

雜談

(以下選自南開大學(xué)出版社出版的《WPF和Silverlight教程》)

3Dmax中的建模模型可以導(dǎo)出為obj文件格式,將此文件導(dǎo)入WPF項目中,由WPF完成對三維造型的貼圖和控制設(shè)計。本例在3Dmax中設(shè)計了1個雙翼開瓶器模型,將“開瓶器.obj”和貼圖材質(zhì)文件都添加到項目中(“素材”文件夾)。圖2-206 的左側(cè)是“開瓶器.obj”文件拖入到【設(shè)計面板】后,在【對象和時間線】面板中看到的結(jié)構(gòu),右側(cè)是貼圖后的開瓶器模型,中間是本例完成的對開瓶器部件進行拆卸和裝配的控制按鈕。下面說明設(shè)計過程。

    1obj文件導(dǎo)入后的對象

2-206左側(cè)看到的是obj文件導(dǎo)入后的對象結(jié)構(gòu),ViewPort3D(命名為viewport3)是三維對象的容器,其中包含相機元素CameraModelVisual3D,默認相機是透視相機PerspectiveCamera(已經(jīng)命名為ppc);World元素(ModelVisual3D)中包含了環(huán)境光子元素AmbientLightContainerModelVisual3D)、方向光子元素DirectionalLightContainerModelVisual3D)和三維造型子元素RootGeometryContainerModelVisual3D),后者又包含了qua023Dmax中的原名)等6ModelVisual3D子元素,每個子元素包含造型元素材質(zhì)設(shè)置DefaultMaterialGeometryModel3D)。

    WPF中對三維模型的控制
圖2-206 開瓶器結(jié)構(gòu)、外觀和控制按鈕

2-1三維造型元素名稱(3Dmax中的原名)和開瓶器部件名稱對照 

三維造型元素名

開瓶器部件名

三維造型元素名

開瓶器部件名

qua01

左翼

Object

開瓶器座

qua02

右翼

Object03

左翼螺釘

pemo

開瓶器把手

Object04

右翼螺釘

2. 三維造型元素初始位置

  obj文件拖入Window3.xaml【設(shè)計面板】后,盡量發(fā)大到和設(shè)計窗口界面一樣大小,這時的大小不一定合適,可以調(diào)節(jié)的照相機初始位置,如圖2-207左圖。其中參數(shù)是調(diào)整后的參數(shù),比如Position,在obj文件剛導(dǎo)入時,X、YZ不一定是目前的數(shù)值,改變Z參數(shù)的數(shù)值可以調(diào)節(jié)三維造型在屏幕中的大小。Direction參數(shù)中的X、Y調(diào)節(jié)到0,相機面向Z坐標軸的負方向。本例中Far Clipping Plane的參數(shù)調(diào)節(jié)的比較大,當(dāng)3D對象縮小的很小時還能完整看到造型全貌。

WPF中對三維模型的控制
2-207 照相機初始位置參數(shù)設(shè)置和World初始變換設(shè)置

另外,“World”元素做了位移變換,見圖2-207右圖,Z坐標使造型大小改變,Y坐標產(chǎn)生上下位移。所有三維造型元素的其他變換參數(shù)默認是0,知道這些參數(shù)的初始值對后面的故事板設(shè)計很重要。

3. 貼圖和光線設(shè)置

貼圖需要的材質(zhì)圖片“金屬7.jpg”和“外殼.jpg”已經(jīng)添加到項目的“素材”文件夾中,將這些圖片拖入【設(shè)計面板】后生成畫刷資源,保存到ResourceDictionary1.xaml資源文件中,用于三維造型元素的材質(zhì)貼圖。“Object”元素(“開瓶器座”)的“DefaultMaterial”貼圖使用了“外殼.jpg”生成的畫刷資源,“螺釘”沒有貼圖,采用“白色”材質(zhì),其余采用“金屬7.jpg 生成的畫刷資源,貼圖過程略。

環(huán)境光“AmbientLight”采用定向光,設(shè)置為白色,方向光DirectionalLight也采用定向光,設(shè)置為白色,調(diào)整初始角度可以明亮照射3D對象。

4. 開瓶器旋轉(zhuǎn)故事板設(shè)計

示例中設(shè)計了1個故事板StoryBoard0(程序中的命名為mystoryboard0),用于實現(xiàn)整個造型的三維空間旋轉(zhuǎn),如圖2-208所示。

WPF中對三維模型的控制
2-208 電動機三維空間旋轉(zhuǎn)故事板設(shè)計

故事板StoryBoard0針對三維元素“World”和方向光DirectionalLight設(shè)置了動畫,故事板中有5個關(guān)鍵幀,“World”圍繞Y軸進行旋轉(zhuǎn)變換(參考圖2-203),分別是0、90、180、270、360,時間間隔供8秒。同時,對方向光進行跟蹤設(shè)置,保證旋轉(zhuǎn)時方向光能夠明亮照射到3D對象。圖2-206中的“旋轉(zhuǎn)”按鈕(名為xuanzhuan)的事件代碼就是啟動此故事板。WPF中設(shè)計故事板時會自動生成事件觸發(fā)器,自動啟動故事板,本例將觸發(fā)器全部刪除,用代碼啟動后停止。

5. 開瓶器部件拆卸和裝配故事板設(shè)計

開瓶器部件拆卸共設(shè)計了5個故事板,StoryBoard1StoryBoard5(程序中的名稱分別是mystoryboard1mystoryboard5),分別順序用于設(shè)計拆卸“左翼螺釘”、“右翼螺釘”、“左翼”、“右翼”、“開瓶器把手”的動畫。

開瓶器部件裝配也設(shè)計了5個故事板,StoryBoard6StoryBoard10(程序中的名稱分別是mystoryboard6mystoryboard10),分別順序用于設(shè)計裝配“開瓶器把手”、 “右翼” 、“左翼”、“右翼螺釘”和“左翼螺釘”的動畫。

拆卸動畫和裝配過程的動畫運動過程是相反的,拆卸動畫的終點參數(shù)應(yīng)該是裝配動畫的起點參數(shù),裝配動畫的終點參數(shù)是拆卸動畫的起點參數(shù),動畫時間間隔可以一樣,運動路徑可以有差異,但起點和終點參數(shù)必須對應(yīng),否則部件就不能還原到原來位置了。動畫設(shè)計過程是雷同的,圖2-209左圖是開瓶器所有可拆卸部件全部拆卸后在屏幕中的放置位置布局。

WPF中對三維模型的控制
2-209 開瓶器部件拆卸后放置在屏幕的位置布局和“開瓶器把手”拆卸故事板設(shè)計

    下面以“開瓶器把手”為例,說明其拆卸動畫和裝配動畫的設(shè)計。

“開瓶器把手”的拆卸動畫故事板是StoryBoard5(程序中名為mystoryboard5),設(shè)計圖如圖2-209右下圖。拆卸故事板有10個關(guān)鍵幀。“開瓶器把手”的裝配動畫故事板是StoryBoard6(程序中名為mystoryboard6),設(shè)計圖如圖2-209右上圖。裝配故事板同樣有10個關(guān)鍵幀。對應(yīng)的變換參數(shù)如表2-2。

    從表2-2的參數(shù)中可以看出拆卸動畫的終點參數(shù)是裝配動畫的起點參數(shù),裝配動畫的終點參數(shù)是拆卸動畫的起點參數(shù),中間的參數(shù)有差異僅僅反映中間運動過程有異,這并不重要。

其他故事版的設(shè)計雷同,不再列出。

6. 程序設(shè)計

程序設(shè)計有下面幾點要說明:

第一,圖2-206中有4個按鈕,其中有1個“復(fù)位”按鈕,恢復(fù)三維對象的原來狀態(tài),使用刪除多于變換的方法?!靶D(zhuǎn)”按鈕啟動的是StoryBoard0故事板?!白詣硬鹦丁卑粹o單擊后將會依次啟動故事板StoryBoard1StoryBoard5,“自動裝配”按鈕單擊后將會依次啟動故事板StoryBoard6StoryBoard10。

第二,故事板的控制沒有使用觸發(fā)器,自動生成的所有觸發(fā)器均被刪除,故事板的控制采用前面介紹過的利用故事板資源設(shè)置代碼控制故事板。

第三,故事板的依次啟動指前一個故事板完成后才能啟動后一個故事版,這樣在程序上需要設(shè)置故事板的Completed事件。

2-2 StoryBoard5StoryBoard6關(guān)鍵幀參數(shù)設(shè)置

時間

拆卸動畫StoryBoard5

裝配動畫StoryBoard6

位移變換參數(shù)

坐標X、Y、Z

旋轉(zhuǎn)變換參數(shù)

角度X、YZ

位移變換參數(shù)

坐標X、Y、Z

旋轉(zhuǎn)變換參數(shù)

角度X、Y、Z

0

0,0,0

0,0,0

0,110,0

0,0,0

1

0,10,0

0,90,0

0,90,0

0,0,0

2

0,20,0

0,180,0

0,70,0

0,0,0

3

0,30,0

0,270,0

0,60,0

0,0,0

4

0,40,0

0,360,0

0,50,0

0,0,0

5

0,50,0

0,90,0

0,40,0

0,0,0

6

0,60,0

0,180,0

0,30,0

0,-90,0

7

0,70,0

0,270,0

0,20,0

0,-180,0

8

0,90,0

0,360,0

0,10,0

0,-270,0

9

0,110,0

0,360,0

0,0,0

0,-360,0

下面是程序代碼,有相關(guān)解釋,不再贅述。

public partial class Window3 : Window

    {

        //旋轉(zhuǎn)故事板

        Storyboard mystoryboard0=new Storyboard();

        //拆卸故事板

        Storyboard mystoryboard1=new Storyboard();

        Storyboard mystoryboard2=new Storyboard();

        Storyboard mystoryboard3=new Storyboard();

        Storyboard mystoryboard4=new Storyboard();

        Storyboard mystoryboard5=new Storyboard();

        //裝配故事板

        Storyboard mystoryboard6=new Storyboard();

        Storyboard mystoryboard7=new Storyboard();

        Storyboard mystoryboard8=new Storyboard();

        Storyboard mystoryboard9=new Storyboard();

        Storyboard mystoryboard10=new Storyboard();

        //定義鼠標跟隨對象,FollowMouse3D是自定義類

        FollowMouse3D fm3d=new FollowMouse3D();

        Point mouseLastPosition;

        //定義變量,記憶相機位置坐標

        double cameraX,cameraY,cameraZ;

        //設(shè)置三維變換組變量

        Transform3DGroup GroupTF3D;

        //記憶三維變換組中的子變換數(shù)

        int transforms;

        public Window3()

        {

            this.InitializeComponent();

            mystoryboard0=(Storyboard)this.FindResource("Storyboard0");

            mystoryboard1=(Storyboard)this.FindResource("Storyboard1");

            mystoryboard2=(Storyboard)this.FindResource("Storyboard2");

            mystoryboard3=(Storyboard)this.FindResource("Storyboard3");

            mystoryboard4=(Storyboard)this.FindResource("Storyboard4");

            mystoryboard5=(Storyboard)this.FindResource("Storyboard5");

            mystoryboard6=(Storyboard)this.FindResource("Storyboard6");

            mystoryboard7=(Storyboard)this.FindResource("Storyboard7");

            mystoryboard8=(Storyboard)this.FindResource("Storyboard8");

            mystoryboard9=(Storyboard)this.FindResource("Storyboard9");

            mystoryboard10=(Storyboard)this.FindResource("Storyboard10");

            //聲明故事板完成事件

            mystoryboard1.Completed+=new System.EventHandler(mystoryboard1_Completed);

            mystoryboard2.Completed+=new System.EventHandler(mystoryboard2_Completed);

            mystoryboard3.Completed+=new System.EventHandler(mystoryboard3_Completed);

            mystoryboard4.Completed+=new System.EventHandler(mystoryboard4_Completed);

            mystoryboard5.Completed+=new System.EventHandler(mystoryboard5_Completed);

            mystoryboard6.Completed+=new System.EventHandler(mystoryboard6_Completed);

            mystoryboard7.Completed+=new System.EventHandler(mystoryboard7_Completed);

            mystoryboard8.Completed+=new System.EventHandler(mystoryboard8_Completed);

            mystoryboard9.Completed+=new System.EventHandler(mystoryboard9_Completed);

            mystoryboard10.Completed+=new System.EventHandler(mystoryboard10_Completed);

            //遠景相機初始位置

            cameraX=ppc.Position.X;

            cameraY=ppc.Position.Y;

            cameraZ=ppc.Position.Z;

            //聲明或獲取當(dāng)前World的三維變換組(xaml中)Transform3DGroup

            GroupTF3D = World.Transform as Transform3DGroup;

            //記錄三維變換組中子變換的總數(shù)

            transforms=GroupTF3D.Children.Count;

            //故事板屬性設(shè)置

            this.mystoryboard0.RepeatBehavior=RepeatBehavior.Forever;

            this.mystoryboard0.FillBehavior=FillBehavior.Stop;

this.mystoryboard0.BeginTime=TimeSpan.FromSeconds(2);

            this.mystoryboard1.BeginTime=TimeSpan.FromSeconds(2);

            this.mystoryboard6.BeginTime=TimeSpan.FromSeconds(2);

            this.mystoryboard0.Begin();

        }

   //復(fù)位按鈕,調(diào)用自定義方法(復(fù)位操作)

private void reset_Click(object sender, System.Windows.RoutedEventArgs e)

        {

            Reset();       

        }

     //自定義方法,復(fù)位操作

    private void Reset(){

            this.mystoryboard0.Stop();

            //恢復(fù)相機初始位置

            ppc.Position = new Point3D(cameraX, cameraY,cameraZ);

            int j=GroupTF3D.Children.Count;

            //保留原來的變換數(shù),其余刪除

            if (j>transforms){         

                for (int k=j-1;k>transforms-1;){

                   GroupTF3D.Children.RemoveAt(k);

                   k=GroupTF3D.Children.Count-1;

                }

            

        }

    //旋轉(zhuǎn)按鈕事件

    private void xuanzhuan_Click(object sender, System.Windows.RoutedEventArgs e)

        {

            this.mystoryboard0.Begin();

        }

    //自動拆卸

    private void button6_Click(object sender, System.Windows.RoutedEventArgs e)

        {

            Reset();

            this.mystoryboard1.Begin();//左翼螺釘拆卸

        }

    private void mystoryboard1_Completed(object sender, System.EventArgs e)

        {

            this.mystoryboard2.Begin();//右翼螺釘拆卸

        }

    private void mystoryboard2_Completed(object sender, System.EventArgs e)

        {

            this.mystoryboard3.Begin();////左翼拆卸

        }

    private void mystoryboard3_Completed(object sender, System.EventArgs e)

        {

            this.mystoryboard4.Begin();//右翼拆卸

        }

    private void mystoryboard4_Completed(object sender, System.EventArgs e)

        {

            this.mystoryboard5.Begin();//開瓶器把手拆卸

        }

    private void mystoryboard5_Completed(object sender, System.EventArgs e)

        {

            this.mystoryboard0.Begin();//拆卸完成啟動旋轉(zhuǎn)故事板

        

    //自動裝配

    private void button7_Click(object sender, System.Windows.RoutedEventArgs e)

        {

            Reset();

            this.mystoryboard6.Begin();//開瓶器把手裝配

        }

    private void mystoryboard6_Completed(object sender, System.EventArgs e)

        {

            this.mystoryboard7.Begin();//右翼裝配

        }

    private void mystoryboard7_Completed(object sender, System.EventArgs e)

        {

            this.mystoryboard8.Begin();//左翼裝配

        }

    private void mystoryboard8_Completed(object sender, System.EventArgs e)

        {

            this.mystoryboard9.Begin();//右翼螺釘裝配

        }

    private void mystoryboard9_Completed(object sender, System.EventArgs e)

        {

            this.mystoryboard10.Begin();//左翼螺釘裝配

        }

    private void mystoryboard10_Completed(object sender, System.EventArgs e)

        {

            this.mystoryboard0.Begin();//裝配完成啟動故事板

            

     }

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約