C#?WPF實現(xiàn)3D操作幾何體效果
操作幾何體
據(jù)說我的世界是三個程序員用一周開發(fā)出來的,那一個程序員用半天開發(fā)出一個乞丐版的我的世界,講道理是完全沒有問題的。
而眾所周知,我的世界就是無數(shù)個像素塊的集合,而像素塊也就是立方體。關于新建立方體,這個大家已經(jīng)非常熟練了,不僅能新建一個立方體,甚至能新建要多少有多少的立方體。
新建正方體
但目前并不能用手新建,所以接下來添加一個快捷方式Ctrl+N來快速創(chuàng)建立方體。當按下Ctrl+N時效果為

這對于已經(jīng)能生成一排立方體的人來說絕對是小意思了,首先在構造函數(shù)中綁定快捷方式
public MainWindow()
{
InitializeComponent();
KeyDown += MainWindow_KeyDown;
}
MainWindow_KeyDown定義為
private void MainWindow_KeyDown(object sender, KeyEventArgs e)
{
if ((Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) && Keyboard.IsKeyDown(Key.N))
{
MeshGeometry3D mesh = MakeCubeMesh(0, 0, 0, 1);
Color color = Color.FromArgb(255, 0, 255, 0);
DiffuseMaterial material = new DiffuseMaterial(new SolidColorBrush(color));
GeometryModel3D model = new GeometryModel3D(mesh, material);
group3d.Children.Add(model);
}
}
其中MakeCubeMesh為自定義的函數(shù),早在本系列第一篇博客就已經(jīng)寫過了,其他諸如光效等亦然。唯一的區(qū)別是這次并不一開始就生成多個立方體,所以無需DefineModel函數(shù)。
設置立方體位置
剛剛雖然新建了一個立方體,但并不能確定立方體的位置,接下來就要新建一個對話框,用以設置新建立方體的位置。
右鍵項目,新建窗口,名為ParaDialog,其xaml為
<Window x:Class="MyWord.ParaDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="輸入?yún)?shù)" Height="180" Width="300">
<DockPanel LastChildFill="True">
<StackPanel DockPanel.Dock="Bottom"
Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="設置" Click="okButton_Click" Margin="5" Width="60" Height="25"/>
<Button Content="取消" IsCancel="True" Margin="5" Width="60" Height="25"/>
</StackPanel>
<UniformGrid Columns="1" Margin="5" x:Name="ufgLabel"/>
<UniformGrid Columns="1" Margin="5" x:Name="ufgTextBox"/>
??????? </DockPanel>
</Window>
其cs的核心代碼為
public partial class ParaDialog : Window
{
static readonly string[] labels = new string[4] { "x坐標", "y坐標", "z坐標", "邊長" };
List<TextBox> paraBoxes = new List<TextBox>();
public double[] para;
public ParaDialog(double[] para)
{
this.para = para;
InitializeComponent();
string tmp;
for (int i = 0; i < 4; i++)
{
//向UniformGrid中歐給填充文字塊
ufgLabel.Children.Add(new TextBlock() { Text = labels[i] });
paraBoxes.Add(new TextBox());
ufgTextBox.Children.Add(paraBoxes[i]);
}
}
private void okButton_Click(object sender, RoutedEventArgs e)
{
for (int i = 0; i < 4; i++)
para[i] = double.Parse(paraBoxes[i].Text);
DialogResult = true;
}
}
最后,更改Ctrl+N的響應代碼
//...前面不用改
if ((Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) && Keyboard.IsKeyDown(Key.N))
{
double[] para = new double[4];
ParaDialog pDialog = new ParaDialog(para);
pDialog.ShowDialog();
if (pDialog.DialogResult != true)
return;
MeshGeometry3D mesh = MakeCubeMesh(para[0],para[1],para[2],para[3]);
//...后面不用改
}

選中立方體
若想操作幾何體,前提是選中它,接下來就綁定一個鼠標動作,來完成選中的操作,先更改xaml代碼,將Viewport3D放到一個border中
<Border Name="mainBorder" Background="White" MouseDown="mainBorder_MouseDown">
<Viewport3D x:Name="v3dMain">
</Viewport3D>
</Border>
然后新建mainBorder_MouseDown函數(shù)
private void mainBorder_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Released) return;
Color color = Color.FromArgb(255, 0, 255, 0);
var material = new DiffuseMaterial(new SolidColorBrush(color));
//獲取鼠標在對象中的位置
Point mousePos = e.GetPosition(v3dMain);
// 執(zhí)行點擊操作
HitTestResult result = VisualTreeHelper.HitTest(v3dMain, mousePos);
//此即鼠標點擊到曲面上的結果
var meshResult = result as RayMeshGeometry3DHitTestResult;
GeometryModel3D model = null;
if ((meshResult != null) && (meshResult.ModelHit is GeometryModel3D))
model = meshResult.ModelHit as GeometryModel3D;
//如果剛才選了別的模型,則使之恢復綠色
if (SelectedModel != null)
SelectedModel.Material = material;
//選擇新的模型
SelectedModel = model;
if (model != null)
model.Material = new DiffuseMaterial(Brushes.Fuchsia);
}
其效果為

挪動幾何體
既然已經(jīng)可以選中了,那么挪動什么的絕對就是小意思了。
回顧此前的鼠標操作攝像機,其基本流程是,鼠標點擊之后,綁定另一個函數(shù),當松開鼠標時解綁。
在WPF 3D中,提供了Tranform成員,可用于移動幾何體,所以在新建幾何體時,務必注意添加一行
//MainWindow_KeyDown函數(shù) model.Transform = new TranslateTransform3D(0, 0, 0);
然后添加全局變量用以保存舊的位置
private Point3D oldPoint;
然后修改mainBorder_MouseDown,其實只需在末尾添加
mainBorder.CaptureMouse(); mainBorder.MouseMove += MainBorder_MouseMove; mainBorder.MouseUp += MainBorder_MouseUp;
接下來是鼠標挪動和彈起時的動作,其中彈起時非常簡單,無非是解綁鼠標動作;而鼠標挪動時,則需更改幾何體的變化參數(shù)。
private void MainBorder_MouseUp(object sender, MouseButtonEventArgs e)
{
mainBorder.ReleaseMouseCapture();
mainBorder.MouseMove -= MainBorder_MouseMove;
mainBorder.MouseUp -= MainBorder_MouseUp;
}
private void MainBorder_MouseMove(object sender, MouseEventArgs e)
{
Point newPoint = e.GetPosition(mainBorder);
var res = VisualTreeHelper.HitTest(v3dMain, newPoint);
if (res == null) return;
var newResult = res as RayMeshGeometry3DHitTestResult;
var deltaPt = newResult.PointHit - oldPoint;
var trans = SelectedModel.Transform as TranslateTransform3D;
trans.OffsetX += deltaPt.X;
trans.OffsetY += deltaPt.Y;
trans.OffsetZ += deltaPt.Z;
oldPoint = newResult.PointHit;
}
效果為

以上就是C# WPF實現(xiàn)3D操作幾何體效果的詳細內容,更多關于C# WPF 3D操作幾何體的資料請關注腳本之家其它相關文章!
相關文章
C#用RabbitMQ實現(xiàn)消息訂閱與發(fā)布
在消息隊列模型中,如何將消息廣播到所有的消費者,這種模式成為“發(fā)布/訂閱”。本文主要以一個簡單的小例子,簡述通過fanout交換機,實現(xiàn)消息的發(fā)布與訂閱,僅供學習分享使用,如有不足之處,還請指正。2021-05-05
C#值類型、引用類型中的Equals和==的區(qū)別淺析
這篇文章主要介紹了C#值類型、引用類型中的Equals和==的區(qū)別淺析,本文分別對C#值類型和引用類型中的Equals和==做了講解和給出了實例,需要的朋友可以參考下2015-01-01
C# Newtonsoft.Json 解析多嵌套json 進行反序列化的實例
這篇文章主要介紹了C# Newtonsoft.Json 解析多嵌套json 進行反序列化的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01
Unity中的RegisterPlugins實用案例深入解析
這篇文章主要為大家介紹了Unity中的RegisterPlugins實用案例深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05
listview控件實現(xiàn)點擊列表頭進行l(wèi)istview排序示例分享
這篇文章主要介紹了listview控件實現(xiàn)點擊列表頭進行l(wèi)istview排序示例分享,需要的朋友可以參考下2014-03-03

