以下是代码流程如下:
1)我从kinect获取深度数据并将其赋予一个计算3d点的函数.
private void display3DView()
{ while(loop_run) { using ( DepthImageFrame depthFrame = sensor.DepthStream.OpenNextFrame(1000)) { if (depthFrame == null) continue; Point3DCollection PointCloud ; depthFrame.CopyDepthImagePixelDataTo(this.depthImagePixels); float[,] ImageArray = new float[320,240]; short [,] depth = new short[240,320]; for (int i = 0; i < 240; i++) { for (int j = 0; j <320; j++) { depth[i,j]= depthImagePixels[j+i *320].Depth; ImageArray[i,j] =(float)depth[i,j]/(float)1000; } } PointCloud =Calculate_PointCloud(ImageArray); viewModel(PointCloud); } } }</i>
2)我用Kinect Camera的摄像机参数和深度数据计算了3D点
private Point3DCollection Calculate_PointCloud(float [,] ImageArray)
{
Point3DCollection PointCloud = new Point3DCollection(); float x_coodinate;`` float y_coordinate; float z_coordinate; float thresholdvalue = 2.0f; for (int i = 0; i < 239; ++i) { for (int j = 0; j < 319; ++j) { if (Math.Abs(ImageArray[i,j] - ImageArray[i,j + 1]) < thresholdvalue && Math.Abs(ImageArray[i,j] - ImageArray[i + 1,j]) < thresholdvalue && Math.Abs(ImageArray[i,j + 1] - ImageArray[i + 1,j]) < thresholdvalue) { z_coordinate = ImageArray[i,j]; x_coodinate = ((j - this.PrincipalPointX) * z_coordinate) / FocalLengthX; y_coordinate = ((i - this.PrincipalPointY) * z_coordinate) / FocalLengthY; Point3D point1 = new Point3D(x_coodinate,y_coordinate,z_coordinate); PointCloud.Add(point1); z_coordinate = ImageArray[i,j + 1]; x_coodinate = (((j + 1) - this.PrincipalPointX) * z_coordinate) / FocalLengthX; y_coordinate = ((i - this.PrincipalPointY) * z_coordinate) / FocalLengthY; Point3D point2 = new Point3D(x_coodinate,z_coordinate); PointCloud.Add(point2); z_coordinate = ImageArray[i + 1,j]; x_coodinate = ((j - this.PrincipalPointX) * z_coordinate) / FocalLengthX; y_coordinate = (((i + 1) - this.PrincipalPointY) * z_coordinate) / FocalLengthY; Point3D point3 = new Point3D(x_coodinate,z_coordinate); PointCloud.Add(point3); } } } return PointCloud; }</i>
3)在这里,我转换为具有每个3D点的法线信息的三角形集合,并将这些三角形给予3D网格对象并使用viewport3D控件渲染3d网格对象
private void viewModel(Point3DCollection points)
{ DirectionalLight DirLight1 = new DirectionalLight(); DirLight1.Color = Colors.White; DirLight1.Direction = new Vector3D(1,1,1); PerspectiveCamera Camera1 = new PerspectiveCamera(); Camera1.FarPlaneDistance = 8000; Camera1.NearPlaneDistance = 100; Camera1.FieldOfView = 10; Camera1.Position = new Point3D(0,1); Camera1.LookDirection = new Vector3D(-1,-1,-1); Camera1.UpDirection = new Vector3D(0,0); bool combinedvertices = true; TriangleModel Triatomesh = new TriangleModel(); MeshGeometry3D tmesh = new MeshGeometry3D(); GeometryModel3D msheet = new GeometryModel3D(); Model3DGroup modelGroup = new Model3DGroup(); ModelVisual3D modelsVisual = new ModelVisual3D(); Viewport3D myViewport = new Viewport3D(); for(int i =0; i<points.Count; i+=3) { Triatomesh.addTriangleToMesh(points[i],points[i + 1],points[i + 2],tmesh,combinedvertices); } msheet.Geometry = tmesh; msheet.Material = new DiffuseMaterial(new SolidColorBrush(Colors.White)); modelGroup.Children.Add(msheet); modelGroup.Children.Add(DirLight1); modelsVisual.Content = modelGroup; myViewport.IsHitTestVisible = false; myViewport.Camera = Camera1; myViewport.Children.Add(modelsVisual); canvas1.Children.Add(myViewport); myViewport.Height = canvas1.Height; myViewport.Width = canvas1.Width; Canvas.SetTop(myViewport,0); Canvas.SetLeft(myViewport,0); } </i>
4)这是一个函数,它通过计算每个3D点的法线来获取三个3D点并将三维网格对象添加为三角形
public void addTriangleToMesh(Point3D p0,Point3D p1,Point3D p2,MeshGeometry3D mesh,bool combine_vertices) { Vector3D normal = CalculateNormal(p0,p1,p2); if (combine_vertices) { addPointCombined(p0,mesh,normal); addPointCombined(p1,normal); addPointCombined(p2,normal); } else { mesh.Positions.Add(p0); mesh.Positions.Add(p1); mesh.Positions.Add(p2); //mesh.TriangleIndices.Add(mesh.TriangleIndices.Count); // mesh.TriangleIndices.Add(mesh.TriangleIndices.Count); // mesh.TriangleIndices.Add(mesh.TriangleIndices.Count); mesh.Normals.Add(normal); mesh.Normals.Add(normal); mesh.Normals.Add(normal); } } public Vector3D CalculateNormal(Point3D P0,Point3D P1,Point3D P2) //static { Vector3D v0 = new Vector3D(P1.X - P0.X,P1.Y - P0.Y,P1.Z - P0.Z); Vector3D v1 = new Vector3D(P2.X - P1.X,P2.Y - P1.Y,P2.Z - P1.Z); return Vector3D.CrossProduct(v0,v1); } public void addPointCombined(Point3D point,Vector3D normal) { bool found = false; int i = 0; foreach (Point3D p in mesh.Positions) { if (p.Equals(point)) { found = true; mesh.TriangleIndices.Add(i); mesh.Positions.Add(point); mesh.Normals.Add(normal); break; } i++; } if (!found) { mesh.Positions.Add(point); mesh.TriangleIndices.Add(mesh.TriangleIndices.Count); mesh.Normals.Add(normal); } }
5)这是我的XAML代码
<Window x:Class="PointCloud3DView.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="PointCloud" Height="653" Width="993" Background="Black" Loaded="Window_Loaded"> <Grid Height="1130" Width="1626"> <Canvas Height="611" HorizontalAlignment="Left" Name="canvas1" VerticalAlignment="Top"
宽度=“967”背景=“黑色”/>
</Grid>
问题是我无法在Wpf Screen中显示3D模型.请问任何人都可以浏览整个代码吗?并让我明白我哪里出错了?并建议我纠正.
提前致谢
解决方法
我现在没有时间检查并尝试整个代码.但是我会尝试三件事:
>我不确定你的相机的方向.它在(0,0),
使用矢量(-1,-1)查找,这意味着它专注于中心
点(-1,-1).这有点奇怪……尝试定位相机
进一步(取决于您的模型的规模),如(0,10,0)或甚至
进一步将其集中在(0,0)或你的中心点的任何地方
模型是:
Camera1.Position = new Point3D(0,0);
Camera1.LookDirection = new Point3D(0,0) – Camera1.Position;
>同时移除定向灯(因为它使用法线,如果它们出错则不会显示任何内容)并尝试环境光.和你的
定向闪电与您的外观正好相反
方向(-1,-1)和(1,1).
>尝试在三角形索引中交换点的顺序(WPF仅渲染网格的一侧,因此模型可能在那里但内部/外部) –
而不是0,2尝试0,2,1;
如果没有任何帮助,我会在回家后尝试你的代码.
/稍后编辑/
在简单的三角形上编写你的代码并根据我的提示重写它并且它有效.有一些评论和两个提示如何清理你的代码:)
private void viewModel(Point3DCollection points) { DirectionalLight DirLight1 = new DirectionalLight(); DirLight1.Color = Colors.White; DirLight1.Direction = new Vector3D(1,1); PerspectiveCamera Camera1 = new PerspectiveCamera(); Camera1.FarPlaneDistance = 8000; //Camera1.NearPlaneDistance = 100; //close object will not be displayed with this option Camera1.FieldOfView = 10; //Camera1.Position = new Point3D(0,1); //Camera1.LookDirection = new Vector3D(-1,-1); Camera1.Position = new Point3D(0,10); Camera1.LookDirection = new Point3D(0,0) - Camera1.Position; //focus camera on real center of your model (0,0) in this case Camera1.UpDirection = new Vector3D(0,0); //you can use constructor to create Camera instead of assigning its properties like: //PerspectiveCamera Camera1 = new PerspectiveCamera(new Point3D(0,10),new Vector3D(0,-1),10); bool combinedvertices = true; TriangleModel Triatomesh = new TriangleModel(); MeshGeometry3D tmesh = new MeshGeometry3D(); GeometryModel3D msheet = new GeometryModel3D(); Model3DGroup modelGroup = new Model3DGroup(); ModelVisual3D modelsVisual = new ModelVisual3D(); Viewport3D myViewport = new Viewport3D(); for (int i = 0; i < points.Count; i += 3) { Triatomesh.addTriangleToMesh(points[i + 2],points[i],combinedvertices); //I did swap order of vertexes you may try both options with your model } msheet.Geometry = tmesh; msheet.Material = new DiffuseMaterial(new SolidColorBrush(Colors.White)); //you can use constructor to create GeometryModel3D instead of assigning its properties like: //msheet = new GeometryModel3D(tmesh,new DiffuseMaterial(new SolidColorBrush(Colors.White))); modelGroup.Children.Add(msheet); //use AMbientLIght instead of directional modelGroup.Children.Add(new AmbientLight(Colors.White)); modelsVisual.Content = modelGroup; myViewport.IsHitTestVisible = false; myViewport.Camera = Camera1; myViewport.Children.Add(modelsVisual); canvas1.Children.Add(myViewport); myViewport.Height = canvas1.Height; myViewport.Width = canvas1.Width; Canvas.SetTop(myViewport,0); Canvas.SetLeft(myViewport,0); }
我使用Points3DCollection作为参数(而不是Kinect输入):
Point3DCollection points = new Point3DCollection(); points.Add(new Point3D(0.5,0.5)); points.Add(new Point3D(0.5,-0.5,-0.5)); points.Add(new Point3D(-0.5,-0.1,-0.5)); viewModel(points);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。