注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

天涯倦客的博客

祝福你朋友永远快乐!

 
 
 

日志

 
 

WPF嵌入3D引擎,极少的解决方案  

2016-02-19 13:19:42|  分类: U3D |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

一,嵌入的流程   1.创建一个WPF工程

   2.创建一个WindowForm自定义控件库(UserControl)      1).引入UintyWebPlayer COM组件

      2).将这个组件拖到UserControl里,并将Dock属性设置为Fill让他充满这个控件(不这么   做,UnityWebPlayer组件大小无法在外层修改)      3).在自定义的程序文件中,增加一个UnityWebPlayer的Public引用,这样做的目的是之后可以对其进行操作

      4).生成,在bin中会有三个DLL文件,只有两个有用,一个是AxInterop.UnityWebPlayerAXLib另一个是以用的DLL

     注:这么做可以动态修改UnityWebPlayer 的SRC属性.   3.将刚制作的DLL引入到WPF工程中,并且再引用System.Windows.Forms与WindowsInteration

   4.在WPF的XAML的window标签中,引入我们自己定义的自定义控件名称,如:xmlns:unity="..." 在<Grid>中,加入一个<WindowsFormHost>标签

     用来承载我们的WidowsForm自定义组件,并在其中加入如<unity:UnitPlayer       x:Name="UnityPlayer">这样,就将UnityWebPlayer嵌入了WPF     当然也可以在C#中动态加载组件,只需要设置WindowsFormHost.Child=UnitPlayer

二,实现Unity3D与WPF的双向通讯

   1.WPF->Unity通讯     1).众所周知,向模型中发送消息的方法为SendMessage方法(不明白自己去百度)     2).SendMessage方法的参数:1.物体名(string) 2方法名(string) 3方法参数(object)

     注:发送SendMessage 方法参数我只成功发送了string类型与int类型.  发送bool类型时,提示COM组件不安全.暂时没有解决.只能修改模型

     中的脚本,将bool类型参数改用string与int接收,并增加了判断.希望有办法解决的朋友们告知一下

   2.鼠标右键的BUG

     1).3D模型基本操作都是鼠标右键按下以后,拖动鼠标可以旋转模型视角,但是WPF加载后的UnityWebPlayer控件存在一个BUG:右键菜单

     2).网上有很多方法去除右键菜单的问题.但都是在网页中去除,UnityWebPlayer封装好的控件还是会携带右键菜单.经过几番周折,也没有直接

        在控件里去除右键菜单的问题.在网上,所有的方法都是在网页中修改JS代码解决右键菜单的问题.但是WPF是没有办法修改JS代码的.因为我

        们不需要用到Untiy3D发布后的html文件.那怎么解决这个问题呢?我的方式是截取鼠标右键的点击,抬起,按下三个事件,在截取的同时,向

        模型中发送鼠标消息.       

/// <summary>      

  /// 封装U3d WebPlayer控件,屏蔽ocx中的鼠标右键显示菜单功能       

 /// </summary>        

public class U3DPlayer:AxUnityWebPlayerAXLib.AxUnityWebPlayer       

{          #region 常量定义,鼠标信息

           private const int WM_RBUTTONDOWN = 0x204;          

           private const int WM_RBUTTONUP = 0x205;          

           private const int WM_RBUTTONBLCLK = 0x206;

         #endregion

 

        /// <summary>      

       /// 屏蔽鼠标右键消息,解决鼠标右键下,会出现菜单的问题       

       /// </summary>        

      /// <param name="msg"></param>       

      /// <returns></returns>        

public override bool PreProcessMessage(ref Message msg)        

{          

switch (msg.Msg)           

   {              

    case 0x204://鼠标右键按下消息                  

this.SendMessage("ThiredViewCamera", "RightMouseButtonDown", null);                   this.SendMessage("FirstViewCamera", "RightMouseButtonDown", null);                   this.SendMessage("Main Camera", "RightMouseButtonDown", null);                  

this.Focus();                  

return true;              

    case 0x205://鼠标右键抬起消息                  

this.SendMessage("ThiredViewCamera", "RightMouseButtonUp", null);                   this.SendMessage("FirstViewCamera", "RightMouseButtonUp", null);                   this.SendMessage("Main Camera", "RightMouseButtonUp", null);                  

return true;              

    case 0x206://鼠标右键点击消息                  

return true;            }           

return base.PreProcessMessage(ref msg);         

   }            

}    

注: 发送的SendMessage中的参数,为我在模型中写好的拖动视角脚本中的方法.需要绕开这个BUG,有可能需要修改Unity3D脚本

        其实,发送鼠标消息通讯的消息流程为 WPF-->OCX-->Unity3D

         现在改为WPF-->Unity3D既跳过为OCX发送鼠标右键的消息,直接向模型中发送消息

    3.Unity3D->WPF通讯

      1).其实,Unity3D与WPF的通讯,也是通过SendMessage来进行交互的,在Unity3D的脚本中,我们可以自定义一个发送消息事件:

         public void OnMouseUp() {   Application.ExternalCall("Ip",aaa);//向客户端发送IP     }

        注:该脚本为当鼠标在绑定该脚本的模型上抬起时,发送Application.ExternallCall消息

          该消息发送到WPF中应为Ip("aaa")是一个字符串,这样你该知道怎么操作了吧.

      2).WPF如何接收发送出来的消息

         在UnityWebPlayer的从元数据中,有这么一个委托(回掉函数),类型如下:

         public event _DUnityWebPlayerAXEvents_OnExternalCallEventHandler OnExternalCall

         是的,在你自己的WPF中建立一个函数,参数与它对应上:如:

           private void ReturnIp(object sender, _DUnityWebPlayerAXEvents_OnExternalCallEvent e)        {               string Ip=e.value;        }

        在实例化时,只需要将UnityWebPlayer的OnExternalCall方法委托为你的方法:

        axPlayer.OnExternalCall+=new _DUnityWebPlayerAXEvents_OnExternalCallEventHandler(ReturnIp);        这样,当UnityWebPlayer发送OnExternalCall消息时,你的WPF程序中就会接收到该消息带来的返回值.

        具体怎么操作就看你自己吧

     4.动态修改Unity3dPlayer的SRC属性

       1).在2.2中,我们截取鼠标消息时,已经实现了一个类,并继承了AxUnityWebPlayerAXLib.AxUnityWebPlayer

       2).将该控件封装到ActiveX中.代码如下:

         public  class Unity3dControl:UserControl         

 {               

 public Unity3dControl()            

       {    

         

        }            

 public void LoadScence(string Src)            

      {                

     if (Src != "" && Src != null)//加载的路径地址不为空               

     {                    

     axPlayer = new U3DPlayer();                    

     this.axPlayer.BeginInit();                    

     base.Controls.Add(this.axPlayer);                    

     this.axPlayer.EndInit();                    

     this.axPlayer.src = Src;                    

     AxHost.State ocxState = this.axPlayer.OcxState;                    

     axPlayer.IsAccessible = false;                    

     this.axPlayer.Dispose();                    

     this.axPlayer = new U3DPlayer();                    

     this.axPlayer.BeginInit();                    

     this.axPlayer.OcxState = ocxState;                    

     this.axPlayer.Dock = DockStyle.Fill;                                      

     base.Controls.Add(this.axPlayer);                

     }            

   }         

}       

好了,这样每当你实例化这个Unity3dControl后,设置其LoadScence中的Src属性,就可以实现动态加载模型了

 

  评论这张
 
阅读(293)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017