/// <summary> /// 重新布局3D内容 /// </summary> void ReLayoutInteractiveVisual3D() { Debug.WriteLine("重新布局3D内容"); Debug.WriteLine("{0} ", this.viewport3D.Children.Count); int j = 0; for (int i = 0; i < this.viewport3D.Children.Count; i++) { InteractiveVisual3D iv3d = this.viewport3D.Children[i] as InteractiveVisual3D; if (iv3d != null) { double angle = 0; double offsetX = 0; double offsetZ = 0; GetTransformOfInteractiveVisual3D(j++, IntermediateIndex, out angle, out offsetX, out offsetZ); //保证中间图片两侧最多只有3张图片 if (i < IntermediateIndex - 2 || i > IntermediateIndex + 4) { Debug.WriteLine("隐藏不需要展示的资源"); angle = 0; offsetX = 500; offsetZ = -1; } NameScope.SetNameScope(this, new NameScope()); this.RegisterName("iv3d", iv3d); Duration time = new Duration(TimeSpan.FromSeconds(0.3)); DoubleAnimation angleAnimation = new DoubleAnimation(angle, time); DoubleAnimation xAnimation = new DoubleAnimation(offsetX, time); DoubleAnimation zAnimation = new DoubleAnimation(offsetZ, time); Storyboard story = new Storyboard(); story.Children.Add(angleAnimation); story.Children.Add(xAnimation); story.Children.Add(zAnimation); Storyboard.SetTargetName(angleAnimation, "iv3d"); Storyboard.SetTargetName(xAnimation, "iv3d"); Storyboard.SetTargetName(zAnimation, "iv3d"); Storyboard.SetTargetProperty( angleAnimation, new PropertyPath("(ModelVisual3D.Transform).(Transform3DGroup.Children)[0].(RotateTransform3D.Rotation).(AxisAngleRotation3D.Angle)")); Storyboard.SetTargetProperty( xAnimation, new PropertyPath("(ModelVisual3D.Transform).(Transform3DGroup.Children)[1].(TranslateTransform3D.OffsetX)")); Storyboard.SetTargetProperty( zAnimation, new PropertyPath("(ModelVisual3D.Transform).(Transform3DGroup.Children)[1].(TranslateTransform3D.OffsetZ)")); story.Begin(this); } } }
/// <summary> /// Returns the intersection info for the given rayHitResult. Intersection info /// only exists for an InteractiveModelVisual3D, so if an InteractiveModelVisual3D /// is not hit, then the return value is null. /// </summary> /// <param name="rayHitResult"></param> /// <returns> /// Returns ClosestIntersectionInfo if an InteractiveModelVisual3D is hit, otherwise /// returns null. /// </returns> private ClosestIntersectionInfo GetIntersectionInfo(RayHitTestResult rayHitResult) { ClosestIntersectionInfo isectInfo = null; // try to cast to a RaymeshGeometry3DHitTestResult RayMeshGeometry3DHitTestResult rayMeshResult = rayHitResult as RayMeshGeometry3DHitTestResult; if (rayMeshResult != null) { // see if we hit an InteractiveVisual3D InteractiveVisual3D imv3D = rayMeshResult.VisualHit as InteractiveVisual3D; if (imv3D != null) { // we can now extract the mesh and visual for the object we hit MeshGeometry3D geom = rayMeshResult.MeshHit; UIElement uiElem = imv3D.InternalVisual; if (uiElem != null) { // pull the barycentric coordinates of the intersection point double vertexWeight1 = rayMeshResult.VertexWeight1; double vertexWeight2 = rayMeshResult.VertexWeight2; double vertexWeight3 = rayMeshResult.VertexWeight3; // the indices in to where the actual intersection occurred int index1 = rayMeshResult.VertexIndex1; int index2 = rayMeshResult.VertexIndex2; int index3 = rayMeshResult.VertexIndex3; // texture coordinates of the three vertices hit // in the case that no texture coordinates are supplied we will simply // treat it as if no intersection occurred if (geom.TextureCoordinates != null && index1 < geom.TextureCoordinates.Count && index2 < geom.TextureCoordinates.Count && index3 < geom.TextureCoordinates.Count) { Point texCoord1 = geom.TextureCoordinates[index1]; Point texCoord2 = geom.TextureCoordinates[index2]; Point texCoord3 = geom.TextureCoordinates[index3]; // get the final uv values based on the barycentric coordinates Point finalPoint = new Point(texCoord1.X * vertexWeight1 + texCoord2.X * vertexWeight2 + texCoord3.X * vertexWeight3, texCoord1.Y * vertexWeight1 + texCoord2.Y * vertexWeight2 + texCoord3.Y * vertexWeight3); // create and return a valid intersection info isectInfo = new ClosestIntersectionInfo(finalPoint, uiElem, imv3D); } } } } return(isectInfo); }
/// <summary> /// Filter for hit testing. In the case that the hidden visual has capture /// then all Visual3Ds are skipped except for the one it is on. This gives the /// same behavior as capture in the 2D case. /// </summary> /// <param name="o"></param> /// <returns></returns> public HitTestFilterBehavior InteractiveMV3DFilter(DependencyObject o) { // by default everything is ok HitTestFilterBehavior behavior = HitTestFilterBehavior.Continue; // if the hidden visual has mouse capture - then we only want to test against // the IMV3D that has capture if (o is Visual3D && _mouseCaptureInHiddenVisual) { if (o is InteractiveVisual3D) { InteractiveVisual3D imv3D = (InteractiveVisual3D)o; if (imv3D.InternalVisual != _hiddenVisual.Child) { behavior = HitTestFilterBehavior.ContinueSkipSelf; } } else { behavior = HitTestFilterBehavior.ContinueSkipSelf; } } return(behavior); }
private InteractiveVisual3D CreateInteractiveVisual3D(UIElement visual, int index) { InteractiveVisual3D iv3d = new InteractiveVisual3D(); iv3d.Visual = this.CreateVisual(visual, index); iv3d.Geometry = this.CreateGeometry3D(); iv3d.Transform = this.CreateEmptyTransform3DGroup(); return(iv3d); }
/// <summary> /// 为指定图片路径创建一个3D视觉对象 /// </summary> /// <param name="path"></param> /// <param name="index"></param> /// <returns></returns> InteractiveVisual3D CreateInteractiveVisual3D(string path, int index) { InteractiveVisual3D visual3D = new InteractiveVisual3D(); visual3D.Visual = CreateVisual(path, index); visual3D.Geometry = CreateGeometry3D(); visual3D.Transform = CreateEmptyTransform3DGroup(); return(visual3D); }
/// <summary> /// 为指定图片路径创建一个3D视觉对象 /// </summary> /// <param name="imageFile"></param> /// <returns></returns> private InteractiveVisual3D CreateInteractiveVisual3D(VideoInfo image, int index) { InteractiveVisual3D iv3d = new InteractiveVisual3D(); iv3d.Visual = this.CreateVisual(image, index); iv3d.Geometry = this.CreateGeometry3D(); iv3d.Transform = this.CreateEmptyTransform3DGroup(); return(iv3d); }
/// <summary> /// 为指定图片路径创建一个3D视觉对象 /// </summary> /// <returns></returns> InteractiveVisual3D CreateInteractiveVisual3D(string path, int index) { Debug.WriteLine("为指定图片路径创建一个3D视觉对象"); InteractiveVisual3D visual3D = new InteractiveVisual3D(); visual3D.Visual = CreateVisual(path, index); visual3D.Geometry = CreateGeometry3D(); visual3D.Transform = CreateEmptyTransform3DGroup(); return(visual3D); }
/// <summary> /// 重新布局3D内容,实现循环展示 /// </summary> void ReLayoutInteractiveVisual3D(List <int> list) { var ivs = this.viewport3D.Children.OfType <InteractiveVisual3D>().ToList(); for (int i = 0; i < list.Count; i++) { InteractiveVisual3D iv3d = ivs[list[i]] as InteractiveVisual3D; if (iv3d != null) { double angle = 0; double offsetX = 0; double offsetZ = 0; GetTransformOfInteractiveVisual3D(i, out angle, out offsetX, out offsetZ); NameScope.SetNameScope(this, new NameScope()); this.RegisterName("iv3d", iv3d); Duration time = new Duration(TimeSpan.FromSeconds(0.3)); DoubleAnimation angleAnimation = new DoubleAnimation(angle, time); DoubleAnimation xAnimation = new DoubleAnimation(offsetX, time); DoubleAnimation zAnimation = new DoubleAnimation(offsetZ, time); Storyboard story = new Storyboard(); story.Children.Add(angleAnimation); story.Children.Add(xAnimation); story.Children.Add(zAnimation); Storyboard.SetTargetName(angleAnimation, "iv3d"); Storyboard.SetTargetName(xAnimation, "iv3d"); Storyboard.SetTargetName(zAnimation, "iv3d"); Storyboard.SetTargetProperty( angleAnimation, new PropertyPath("(ModelVisual3D.Transform).(Transform3DGroup.Children)[0].(RotateTransform3D.Rotation).(AxisAngleRotation3D.Angle)")); Storyboard.SetTargetProperty( xAnimation, new PropertyPath("(ModelVisual3D.Transform).(Transform3DGroup.Children)[1].(TranslateTransform3D.OffsetX)")); Storyboard.SetTargetProperty( zAnimation, new PropertyPath("(ModelVisual3D.Transform).(Transform3DGroup.Children)[1].(TranslateTransform3D.OffsetZ)")); story.Begin(this); } } }
/// <summary> /// Function to deal with mouse capture when off the mesh. /// </summary> /// <param name="imv3DHit">The model hit</param> /// <param name="mousePos">The location of the mouse</param> private void HandleMouseCaptureButOffMesh(InteractiveVisual3D imv3DHit, Point mousePos) { // process the mouse capture if it exists UIElement uie = (UIElement)Mouse.Captured; // get the size of the element Rect contBounds = VisualTreeHelper.GetDescendantBounds(uie); // translate to the parent's coordinate system GeneralTransform gt = uie.TransformToAncestor(_hiddenVisual); Point[] visCorners = new Point[4]; // get the points relative to the parent visCorners[0] = gt.Transform(new Point(contBounds.Left, contBounds.Top)); visCorners[1] = gt.Transform(new Point(contBounds.Right, contBounds.Top)); visCorners[2] = gt.Transform(new Point(contBounds.Right, contBounds.Bottom)); visCorners[3] = gt.Transform(new Point(contBounds.Left, contBounds.Bottom)); // get the u,v texture coordinate values of the above points Point[] texCoordsOfInterest = new Point[4]; for (int i = 0; i < visCorners.Length; i++) { texCoordsOfInterest[i] = VisualCoordsToTextureCoords(visCorners[i], _hiddenVisual); } // get the edges that map to the given visual List <HitTestEdge> edges = imv3DHit.GetVisualEdges(texCoordsOfInterest); if (Debug) { AdornerLayer myAdornerLayer = AdornerLayer.GetAdornerLayer(this); if (_DEBUGadorner == null) { _DEBUGadorner = new DebugEdgesAdorner(this, edges); myAdornerLayer.Add(_DEBUGadorner); } else { myAdornerLayer.Remove(_DEBUGadorner); _DEBUGadorner = new DebugEdgesAdorner(this, edges); myAdornerLayer.Add(_DEBUGadorner); } } // find the closest intersection of the mouse position and the edge list FindClosestIntersection(mousePos, edges, imv3DHit); }
private void ReLayoutInteractiveVisual3D() { int j = 0; for (int i = 0; i < this.viewport3D.Children.Count; i++) { InteractiveVisual3D iv3d = this.viewport3D.Children[i] as InteractiveVisual3D; if (iv3d != null) { double angle = 0; double offsetX = 0; double offsetZ = 0; this.GetTransformOfInteractiveVisual3D(j++, this.CurrentMidIndex, out angle, out offsetX, out offsetZ); NameScope.SetNameScope(this, new NameScope()); this.RegisterName("iv3d", iv3d); Duration time = new Duration(TimeSpan.FromSeconds(0.3)); DoubleAnimation angleAnimation = new DoubleAnimation(angle, time); DoubleAnimation xAnimation = new DoubleAnimation(offsetX, time); DoubleAnimation zAnimation = new DoubleAnimation(offsetZ, time); Storyboard story = new Storyboard(); story.Children.Add(angleAnimation); story.Children.Add(xAnimation); story.Children.Add(zAnimation); Storyboard.SetTargetName(angleAnimation, "iv3d"); Storyboard.SetTargetName(xAnimation, "iv3d"); Storyboard.SetTargetName(zAnimation, "iv3d"); Storyboard.SetTargetProperty( angleAnimation, new PropertyPath("(ModelVisual3D.Transform).(Transform3DGroup.Children)[0].(RotateTransform3D.Rotation).(AxisAngleRotation3D.Angle)")); Storyboard.SetTargetProperty( xAnimation, new PropertyPath("(ModelVisual3D.Transform).(Transform3DGroup.Children)[1].(TranslateTransform3D.OffsetX)")); Storyboard.SetTargetProperty( zAnimation, new PropertyPath("(ModelVisual3D.Transform).(Transform3DGroup.Children)[1].(TranslateTransform3D.OffsetZ)")); story.Completed += ChangeApp_Completed; story.Begin(this); } } }
private void LoadModulesToViewport3D(List <UIElement> modules) { if (modules == null) { return; } for (int i = 0; i < modules.Count; i++) { InteractiveVisual3D iv3d = this.CreateInteractiveVisual3D(modules[i], i); this.viewport3D.Children.Add(iv3d); } this.ReLayoutInteractiveVisual3D(); }
private void ReLayoutInteractiveVisual3D() { int j = 0; for (int i = 0; i < this.viewport3D.Children.Count; i++) { InteractiveVisual3D iv3d = this.viewport3D.Children[i] as InteractiveVisual3D; if (iv3d != null) { double angle = 0; double offsetX = 0; double offsetZ = 0; this.GetTransformOfInteractiveVisual3D(j++, this.CurrentMidIndex, out angle, out offsetX, out offsetZ); // NameScope.SetNameScope(this, new NameScope()); // this.RegisterName("iv3d", iv3d); //DoubleAnimation angleAnimation = new DoubleAnimation(angle, time); angleAnimation.To = angle; xAnimation.To = offsetX; zAnimation.To = offsetZ; //DoubleAnimation xAnimation = new DoubleAnimation(offsetX, time); //DoubleAnimation zAnimation = new DoubleAnimation(offsetZ, time); //Storyboard story = new Storyboard(); if (story.Children.Count == 0) { story.Children.Add(angleAnimation); story.Children.Add(xAnimation); story.Children.Add(zAnimation); } //Storyboard.SetTargetName(angleAnimation, "iv3d"); //Storyboard.SetTargetName(xAnimation, "iv3d"); //Storyboard.SetTargetName(zAnimation, "iv3d"); Storyboard.SetTarget(angleAnimation, iv3d); Storyboard.SetTarget(xAnimation, iv3d); Storyboard.SetTarget(zAnimation, iv3d); //Storyboard.SetTargetProperty( // angleAnimation, // p1); //Storyboard.SetTargetProperty( // xAnimation, // p2); //Storyboard.SetTargetProperty( // zAnimation, // p3); story.Begin(this); } } }
/// <summary> /// 加载模型到3D视口 /// </summary> /// <param name="source"></param> private void LoadModelToViewport3D(IList <string> source) { if (source == null || source.Count == 0) { return; } for (int i = 0; i < source.Count; i++) { string imageFile = source[i]; InteractiveVisual3D iv3d = this.CreateInteractiveVisual3D(imageFile, i); this.viewport3D.Children.Add(iv3d); } //确定中间索引 IntermediateIndex = Count / 2; }
/// <summary> /// 添加图片到视口 /// </summary> /// <param name="images"></param> private void LoadImageToViewport3D(List <VideoInfo> images) { if (images == null) { return; } for (int i = 0; i < images.Count; i++) { //string imageFile = images[i].ThumbPath; InteractiveVisual3D iv3d = this.CreateInteractiveVisual3D(images[i], i); items.Add(iv3d); this.viewport3D.Children.Add(iv3d); } this.ReLayoutInteractiveVisual3D(); }
/// <summary> /// 添加图片到视口 /// </summary> /// <param name="images"></param> void LoadImageToViewport3D(List <string> images) { Debug.WriteLine("添加图片到视口"); if (images == null) { return; } for (int i = 0; i < images.Count; i++) { string imageFile = images[i]; InteractiveVisual3D iv3d = this.CreateInteractiveVisual3D(imageFile, i); this.viewport3D.Children.Add(iv3d); } ReLayoutInteractiveVisual3D(); }
public void showImgList(List <BitmapImage> images) { if (images == null) { return; } this.viewport3D.Children.Clear(); for (int i = 0; i < images.Count; i++) { InteractiveVisual3D iv3d = new InteractiveVisual3D(); iv3d.Visual = this.CreateVisual(images[i], i); iv3d.Geometry = this.CreateGeometry3D(); iv3d.Transform = this.CreateEmptyTransform3DGroup(); ModelVisual3D Panel = new ModelVisual3D(); AmbientLight Light = new AmbientLight(); Panel.Content = Light; this.viewport3D.Children.Add(Panel); this.viewport3D.Children.Add(iv3d); } this.CurrentMidIndex = (int)(images.Count / 2); this.ReLayoutInteractiveVisual3D(); }
/// <summary> /// Finds the point in edges that is closest ot the mouse position. Updates closestIntersectionInfo /// with the results of this calculation /// </summary> /// <param name="mousePos">The mouse position</param> /// <param name="edges">The edges to test against</param> /// <param name="imv3DHit">The model that has the visual on it with capture</param> private void FindClosestIntersection(Point mousePos, List <HitTestEdge> edges, InteractiveVisual3D imv3DHit) { double closestDistance = Double.MaxValue; Point closestIntersection = new Point(); // the uv of the closest intersection // Find the closest point to the mouse position for (int i = 0; i < edges.Count; i++) { Vector v1 = mousePos - edges[i]._p1Transformed; Vector v2 = edges[i]._p2Transformed - edges[i]._p1Transformed; Point currClosest; double distance; // calculate the distance from the mouse position to this edge // The closest distance can be computed by projecting v1 on to v2. If the // projectiong occurs between _p1Transformed and _p2Transformed, then this is the // closest point. Otherwise, depending on which side it lies, it is either _p1Transformed // or _p2Transformed. // // The projection equation is given as: (v1 DOT v2) / (v2 DOT v2) * v2. // v2 DOT v2 will always be positive. Thus, if v1 DOT v2 is negative, we know the projection // will occur before _p1Transformed (and so it is the closest point). If (v1 DOT v2) is greater // than (v2 DOT v2), then we have gone passed _p2Transformed and so it is the closest point. // Otherwise the projection gives us this value. // double denom = v2 * v2; if (denom == 0) { currClosest = edges[i]._p1Transformed; distance = v1.Length; } else { double numer = v2 * v1; if (numer < 0) { currClosest = edges[i]._p1Transformed; } else { if (numer > denom) { currClosest = edges[i]._p2Transformed; } else { currClosest = edges[i]._p1Transformed + (numer / denom) * v2; } } distance = (mousePos - currClosest).Length; } // see if we found a new closest distance if (distance < closestDistance) { closestDistance = distance; if (denom != 0) { closestIntersection = ((currClosest - edges[i]._p1Transformed).Length / Math.Sqrt(denom) * (edges[i]._uv2 - edges[i]._uv1)) + edges[i]._uv1; } else { closestIntersection = edges[i]._uv1; } } } if (closestDistance != Double.MaxValue) { UIElement uiElemWCapture = (UIElement)Mouse.Captured; UIElement uiElemOnMesh = imv3DHit.InternalVisual; Rect contBounds = VisualTreeHelper.GetDescendantBounds(uiElemWCapture); Point ptOnVisual = TextureCoordsToVisualCoords(closestIntersection, uiElemOnMesh); Point ptRelToCapture = uiElemOnMesh.TransformToDescendant(uiElemWCapture).Transform(ptOnVisual); // we want to "ring" around the outside so things like buttons are not pressed // this code here does that - the +BUFFER_SIZE and -BUFFER_SIZE are to give a bit of a // buffer for any numerical issues if (ptRelToCapture.X <= contBounds.Left + 1) { ptRelToCapture.X -= BUFFER_SIZE; } if (ptRelToCapture.Y <= contBounds.Top + 1) { ptRelToCapture.Y -= BUFFER_SIZE; } if (ptRelToCapture.X >= contBounds.Right - 1) { ptRelToCapture.X += BUFFER_SIZE; } if (ptRelToCapture.Y >= contBounds.Bottom - 1) { ptRelToCapture.Y += BUFFER_SIZE; } Point finalVisualPoint = uiElemWCapture.TransformToAncestor(uiElemOnMesh).Transform(ptRelToCapture); _closestIntersectInfo = new ClosestIntersectionInfo(VisualCoordsToTextureCoords(finalVisualPoint, uiElemOnMesh), imv3DHit.InternalVisual, imv3DHit); } }
public ClosestIntersectionInfo(Point p, UIElement v, InteractiveVisual3D iv3D) { _pointHit = p; _uiElemHit = v; _imv3DHit = iv3D; }