protected override void Initialise() { //create the camera Xen.Camera.FirstPersonControlledCamera3D camera = new Xen.Camera.FirstPersonControlledCamera3D(this.UpdateManager,Vector3.Zero); camera.Projection.FarClip *= 10; this.camera = camera; //create the draw target. drawToScreen = new DrawTargetScreen(camera); //25,000 instances const int instanceCount = 25000; const float areaRadius = 500; //setup the two draw lists this.staticDrawList = new ToggleDrawList(); this.dynamicDrawList = new ToggleDrawList(); //geometry that will be drawn var geometry = new Xen.Ex.Geometry.Sphere(Vector3.One, 2, true, false, false); //create the mesh instance drawer, (but add it to the screen later) var meshDrawer = new DynamicInstancedMeshGeometry(instanceCount, geometry); var staticMeshDrawer = new StaticInstancedMeshGeometry(instanceCount, geometry); //the dynamicly culled instances are added to a StaticBinaryTreePartition, which //sorts the items into a binary tree, for more efficient culling. //This class assumes it's children do not move (ie they are static) var sceneTree = new Xen.Ex.Scene.StaticBinaryTreePartition(); //add it to the dynamic list dynamicDrawList.Children.Add(sceneTree); //create the instances Random random = new Random(); for (int i = 0; i < instanceCount; i++) { //create a random position in a sphere Vector3 position = new Vector3( (float)(random.NextDouble()-.5), (float)(random.NextDouble()-.5), (float)(random.NextDouble()-.5)); position.Normalize(); position *= (float)Math.Sqrt(random.NextDouble()) * areaRadius; //create the instance var instance = new DynamicMeshInstance(meshDrawer, position); //add the instance to the StaticBinaryTreePartition sceneTree.Add(instance); //add the details of this instance to the static drawer staticMeshDrawer.AddStaticInstance(Matrix.CreateTranslation(position), 1); } //now add the drawer (instances will be drawn by the StaticBinaryPartition, before the drawer) dynamicDrawList.Children.Add(meshDrawer); //now add the static mesh drawer staticDrawList.Children.Add(staticMeshDrawer); //finally, add them both to the screen this.drawToScreen.Add(dynamicDrawList); this.drawToScreen.Add(staticDrawList); //Note that if the StaticBinaryTreePartition was not used, then //in each frame, every single instance would perform a CullTest to the screen //CullTests, despite their simplicity can be very costly in large numbers. //The StaticBinaryTreePartition will usually perform a maximum number of CullTests //that is approximately ~30% the number of children. (in this case, ~8000 tests) //At it's best, when it's entirely off or on screen, it will perform only 1 or 2 CullTests. //The number of cull tests performed will be displayed in debug builds of this tutorial: //add some statusText to display on screen to show the stats statusText = new TextElement(); statusText.Position = new Vector2(50, -50); drawToScreen.Add(statusText); //add the cull test visualiser this.cullVis = new Xen.Ex.Scene.CullTestVisualizer(); drawToScreen.AddModifier(cullVis); }
public DynamicMeshInstance(DynamicInstancedMeshGeometry parent, Vector3 translation) { if (parent == null) throw new ArgumentNullException(); this.parent = parent; this.translation = translation; }