/// <summary> /// Constructor /// </summary> /// <param name="plane">Plane</param> /// <param name="normal">Normal</param> protected BSPTree(BSPTree parent, IList <IBSPItem> items, PartitionHandler partitionHandler) { this.parent = parent; bounds = GetBounds(items); partition = DeterminePartition(items, bounds, partitionHandler); if (items.Count == 1) { this.items.Add(items[0]); } else { List <IBSPItem> backItems = new List <IBSPItem>(); List <IBSPItem> frontItems = new List <IBSPItem>(); foreach (IBSPItem item in items) { Add(item, backItems, frontItems); } if (backItems.Count > 0) { back = new BSPTree(this, backItems, partitionHandler); } if (frontItems.Count > 0) { front = new BSPTree(this, frontItems, partitionHandler); } } }
/// <summary> /// Find leaf closest to point /// </summary> /// <param name="point">Point</param> public BSPTree FindLeaf(Point3D point) { BSPTree last = this; BSPTree tree = this; while (tree != null) { tree = tree.FindNext(point); if (tree != null) { last = tree; } } return(last); }
/// <summary> /// Render 3D scene /// </summary> /// <param name="tree">BSP tree</param> /// <param name="camera">Camera</param> /// <param name="frustum">View frustum</param> /// <param name="depthPlanes">Depth planes</param> private void Render3D(BSPTree tree, IList <IBSPItem> items, Point3D cameraPos, Matrix3D displayMatrix, Frustum frustum, DepthPlanes depthPlanes) { bool clipFade = ClipFade; bool showCubes = ShowCubes; bool limitDepth = LimitDepth; MeshGeometry3D thumbnailMesh = new MeshGeometry3D(); MeshGeometry3D mesh = new MeshGeometry3D(); //MeshGeometry3D flatMesh = new MeshGeometry3D(); // List<BSPCube> renderItems = new List<BSPCube>(); foreach (BSPCube cube in items) { ContainmentType type = frustum.Contains(cube.Bounds); if (type != ContainmentType.Disjoint && (clipFade || type != ContainmentType.Intersects) && (!limitDepth || depthPlanes.Includes(cube.Position))) { double alpha = (type == ContainmentType.Intersects) ? 0.2 : 1.0; if (!string.IsNullOrEmpty(cube.Url) || EmptyImages) { cube.RenderThumbnail(thumbnailMesh, cameraPos, alpha, displayMatrix, thumbnails); } if (showCubes) { cube.Render(mesh, cameraPos, alpha); } //cube.RenderFlat( flatMesh, cameraPos, displayMatrix, new Rect( 0, 0, 0.5, 1 ) ); } } geometry.Geometry = mesh; thumbnailGeometry.Geometry = thumbnailMesh; //flatGeometry.Geometry = flatMesh; }
/* /// <summary> * /// Render 2D scene * /// </summary> * /// <param name="tree">BSP tree</param> * /// <param name="camera">Camera</param> * /// <param name="frustum">View frustum</param> * /// <param name="depthPlanes">Depth planes</param> * private void Render2D( BSPTree tree, IList<IBSPItem> items, Point3D cameraPos, Matrix3D displayMatrix, Frustum frustum, DepthPlanes depthPlanes ) * { * int index = 0; * bool clipFade = ClipFade; * * foreach ( BSPCube cube in items ) * { * ContainmentType type = frustum.Contains( cube.Bounds ); * * if ( type != ContainmentType.Disjoint * && ( clipFade || type != ContainmentType.Intersects ) * && depthPlanes.Includes( cube.Position ) ) * { * Sphere sphere; * * if ( index < canvas.Children.Count ) sphere = canvas.Children[ index ] as Sphere; * else canvas.Children.Add( sphere = new Sphere() ); * * sphere.Visibility = Visibility.Visible; * sphere.RenderTransform = new MatrixTransform( cube.SphereMatrix( cameraPos, displayMatrix ) ); * sphere.Brush = ( cube.MaterialOffset >= 0.5 ) ? SphereBrush : SelectedSphereBrush; * sphere.Opacity = Math.Abs( 0.5 - cube.MaterialOffset ) * 2; * * if ( type == ContainmentType.Intersects ) sphere.Opacity *= 0.2; * ++index; * } * } * * while ( index < canvas.Children.Count ) canvas.Children[ index++ ].Visibility = Visibility.Hidden; * } */ /// <summary> /// Recursively render tree /// </summary> /// <param name="tree">Tree node</param> private void RenderTree(BSPTree tree, IList <IBSPItem> items, Point3D cameraPos, Frustum frustum, DepthPlanes depthPlanes) { bool limitDepth = LimitDepth; if (tree != null && frustum.Contains(tree.Bounds) != ContainmentType.Disjoint && (!limitDepth || depthPlanes.Includes(tree.Bounds))) { Halfspace halfspace = tree.Partition.Classify(cameraPos); if (halfspace == Halfspace.Negative) { if (tree.Front != null) { RenderTree(tree.Front, items, cameraPos, frustum, depthPlanes); } } else if (tree.Back != null) { RenderTree(tree.Back, items, cameraPos, frustum, depthPlanes); } foreach (IBSPItem item in tree.Items) { items.Add(item); } if (halfspace == Halfspace.Negative) { if (tree.Back != null) { RenderTree(tree.Back, items, cameraPos, frustum, depthPlanes); } } else if (tree.Front != null) { RenderTree(tree.Front, items, cameraPos, frustum, depthPlanes); } } }
/// <summary> /// Constructor /// </summary> /// <param name="plane">Plane</param> /// <param name="normal">Normal</param> protected BSPTree( BSPTree parent, IList<IBSPItem> items, PartitionHandler partitionHandler ) { this.parent = parent; bounds = GetBounds( items ); partition = DeterminePartition( items, bounds, partitionHandler ); if ( items.Count == 1 ) { this.items.Add( items[ 0 ] ); } else { List<IBSPItem> backItems = new List<IBSPItem>(); List<IBSPItem> frontItems = new List<IBSPItem>(); foreach ( IBSPItem item in items ) { Add( item, backItems, frontItems ); } if ( backItems.Count > 0 ) back = new BSPTree( this, backItems, partitionHandler ); if ( frontItems.Count > 0 ) front = new BSPTree( this, frontItems, partitionHandler ); } }
/// <summary> /// Build the scene /// </summary> private void BuildScene() { tree = null; Facts facts = DataContext as Facts; dimensionSize = (facts != null) ? Math.Max(Math.Max(facts.What.Count, facts.Where.Count), facts.When.Count) : 8; double scale = (1d / (dimensionSize - 1)) * 0.9; Matrix3D scaleMatrix = new Matrix3D(); scaleMatrix.Scale(new Vector3D(scale, scale, scale)); Random rand = new Random(); MeshGeometry3D cubeMesh = Resources["cubeMesh"] as MeshGeometry3D; List <IBSPItem> items = new List <IBSPItem>(); for (int whatIndex = 0; whatIndex < dimensionSize; ++whatIndex) { double x = ((double)whatIndex / (dimensionSize - 1)) - 0.5d; for (int whereIndex = 0; whereIndex < dimensionSize; ++whereIndex) { double y = ((double)whereIndex / (dimensionSize - 1)) - 0.5d; for (int whenIndex = 0; whenIndex < dimensionSize; ++whenIndex) { double z = ((double)whenIndex / (dimensionSize - 1)) - 0.5d; bool valid = true; double materialOffset; Facts.FactRow fact = null; if (facts != null) { valid = (whatIndex < facts.What.Count) && (whereIndex < facts.Where.Count) & (whenIndex < facts.When.Count); if (valid) { fact = facts.Fact.FindByWhatWhereWhen( facts.What[whatIndex].ID, facts.Where[whereIndex].ID, facts.When[whenIndex].ID); valid = (fact != null); } materialOffset = valid ? 0.4 : 0.55; } else { double alpha = (0.4 + (rand.NextDouble() * 0.6)); // Negative for red, positive for blue materialOffset = ((rand.Next(5) == 2) ? -alpha : alpha) * 0.5 + 0.5; } Matrix3D matrix = scaleMatrix; matrix.Translate(new Vector3D(x, y, z)); string uri = (fact != null) ? fact.ThumbnailUrl : null; items.Add(new BSPCube(matrix, materialOffset, cubeMesh, uri)); } } } tree = new BSPTree(items, new BSPTree.PartitionHandler(TreePartition)); }
/* /// <summary> /// Render 2D scene /// </summary> /// <param name="tree">BSP tree</param> /// <param name="camera">Camera</param> /// <param name="frustum">View frustum</param> /// <param name="depthPlanes">Depth planes</param> private void Render2D( BSPTree tree, IList<IBSPItem> items, Point3D cameraPos, Matrix3D displayMatrix, Frustum frustum, DepthPlanes depthPlanes ) { int index = 0; bool clipFade = ClipFade; foreach ( BSPCube cube in items ) { ContainmentType type = frustum.Contains( cube.Bounds ); if ( type != ContainmentType.Disjoint && ( clipFade || type != ContainmentType.Intersects ) && depthPlanes.Includes( cube.Position ) ) { Sphere sphere; if ( index < canvas.Children.Count ) sphere = canvas.Children[ index ] as Sphere; else canvas.Children.Add( sphere = new Sphere() ); sphere.Visibility = Visibility.Visible; sphere.RenderTransform = new MatrixTransform( cube.SphereMatrix( cameraPos, displayMatrix ) ); sphere.Brush = ( cube.MaterialOffset >= 0.5 ) ? SphereBrush : SelectedSphereBrush; sphere.Opacity = Math.Abs( 0.5 - cube.MaterialOffset ) * 2; if ( type == ContainmentType.Intersects ) sphere.Opacity *= 0.2; ++index; } } while ( index < canvas.Children.Count ) canvas.Children[ index++ ].Visibility = Visibility.Hidden; } */ /// <summary> /// Recursively render tree /// </summary> /// <param name="tree">Tree node</param> private void RenderTree( BSPTree tree, IList<IBSPItem> items, Point3D cameraPos, Frustum frustum, DepthPlanes depthPlanes ) { bool limitDepth = LimitDepth; if ( tree != null && frustum.Contains( tree.Bounds ) != ContainmentType.Disjoint && ( !limitDepth || depthPlanes.Includes( tree.Bounds ) ) ) { Halfspace halfspace = tree.Partition.Classify( cameraPos ); if ( halfspace == Halfspace.Negative ) { if ( tree.Front != null ) RenderTree( tree.Front, items, cameraPos, frustum, depthPlanes ); } else if ( tree.Back != null ) RenderTree( tree.Back, items, cameraPos, frustum, depthPlanes ); foreach ( IBSPItem item in tree.Items ) items.Add( item ); if ( halfspace == Halfspace.Negative ) { if ( tree.Back != null ) RenderTree( tree.Back, items, cameraPos, frustum, depthPlanes ); } else if ( tree.Front != null ) RenderTree( tree.Front, items, cameraPos, frustum, depthPlanes ); } }
/// <summary> /// Render 3D scene /// </summary> /// <param name="tree">BSP tree</param> /// <param name="camera">Camera</param> /// <param name="frustum">View frustum</param> /// <param name="depthPlanes">Depth planes</param> private void Render3D( BSPTree tree, IList<IBSPItem> items, Point3D cameraPos, Matrix3D displayMatrix, Frustum frustum, DepthPlanes depthPlanes ) { bool clipFade = ClipFade; bool showCubes = ShowCubes; bool limitDepth = LimitDepth; MeshGeometry3D thumbnailMesh = new MeshGeometry3D(); MeshGeometry3D mesh = new MeshGeometry3D(); //MeshGeometry3D flatMesh = new MeshGeometry3D(); // List<BSPCube> renderItems = new List<BSPCube>(); foreach ( BSPCube cube in items ) { ContainmentType type = frustum.Contains( cube.Bounds ); if ( type != ContainmentType.Disjoint && ( clipFade || type != ContainmentType.Intersects ) && ( !limitDepth || depthPlanes.Includes( cube.Position ) ) ) { double alpha = ( type == ContainmentType.Intersects ) ? 0.2 : 1.0; if ( !string.IsNullOrEmpty( cube.Url ) || EmptyImages ) { cube.RenderThumbnail( thumbnailMesh, cameraPos, alpha, displayMatrix, thumbnails ); } if ( showCubes ) cube.Render( mesh, cameraPos, alpha ); //cube.RenderFlat( flatMesh, cameraPos, displayMatrix, new Rect( 0, 0, 0.5, 1 ) ); } } geometry.Geometry = mesh; thumbnailGeometry.Geometry = thumbnailMesh; //flatGeometry.Geometry = flatMesh; }
/// <summary> /// Build the scene /// </summary> private void BuildScene() { tree = null; Facts facts = DataContext as Facts; dimensionSize = ( facts != null ) ? Math.Max( Math.Max( facts.What.Count, facts.Where.Count ), facts.When.Count ) : 8; double scale = ( 1d / ( dimensionSize - 1 ) ) * 0.9; Matrix3D scaleMatrix = new Matrix3D(); scaleMatrix.Scale( new Vector3D( scale, scale, scale ) ); Random rand = new Random(); MeshGeometry3D cubeMesh = Resources[ "cubeMesh" ] as MeshGeometry3D; List<IBSPItem> items = new List<IBSPItem>(); for ( int whatIndex = 0; whatIndex < dimensionSize; ++whatIndex ) { double x = ( (double)whatIndex / ( dimensionSize - 1 ) ) - 0.5d; for ( int whereIndex = 0; whereIndex < dimensionSize; ++whereIndex ) { double y = ( (double)whereIndex / ( dimensionSize - 1 ) ) - 0.5d; for ( int whenIndex = 0; whenIndex < dimensionSize; ++whenIndex ) { double z = ( (double)whenIndex / ( dimensionSize - 1 ) ) - 0.5d; bool valid = true; double materialOffset; Facts.FactRow fact = null; if ( facts != null ) { valid = ( whatIndex < facts.What.Count ) && ( whereIndex < facts.Where.Count ) & ( whenIndex < facts.When.Count ); if ( valid ) { fact = facts.Fact.FindByWhatWhereWhen( facts.What[ whatIndex ].ID, facts.Where[ whereIndex ].ID, facts.When[ whenIndex ].ID ); valid = ( fact != null ); } materialOffset = valid ? 0.4 : 0.55; } else { double alpha = ( 0.4 + ( rand.NextDouble() * 0.6 ) ); // Negative for red, positive for blue materialOffset = ( ( rand.Next( 5 ) == 2 ) ? -alpha : alpha ) * 0.5 + 0.5; } Matrix3D matrix = scaleMatrix; matrix.Translate( new Vector3D( x, y, z ) ); string uri = ( fact != null ) ? fact.ThumbnailUrl : null; items.Add( new BSPCube( matrix, materialOffset, cubeMesh, uri ) ); } } } tree = new BSPTree( items, new BSPTree.PartitionHandler( TreePartition ) ); }