public void AddVisible(Tree t, bool branchesVisible, bool frondsVisible, bool leavesVisible, bool billboardsVisible)
 {
     if (branchesVisible)
     {
         visibleBranches.Add(t);
     }
     if (frondsVisible)
     {
         visibleFronds.Add(t);
     }
     if (leavesVisible)
     {
         visibleLeaves.Add(t);
     }
     if (billboardsVisible)
     {
         visibleBillboards.Add(t);
     }
 }
        public TreeGroup(String filename, float size, float sizeVariance, SpeedWindWrapper speedWind, Forest forest, List<Vector3> locations)
        {
            if (!initialized)
            {
                Initialize();
            }

            name = String.Format("Forest: {0} File: {1} Instances: {2}", forest.Name, filename, locations.Count);
            this.forest = forest;

            this.speedWind = speedWind;

            speedTree = new SpeedTreeWrapper();

            speedTree.TextureFlip = true;
            LoadTree(filename);
            speedTree.BranchWindMethod = WindMethod.WindGPU;
            speedTree.FrondWindMethod = WindMethod.WindGPU;
            speedTree.LeafWindMethod = WindMethod.WindGPU;

            float originalSize = 0f;
            float variance = 0f;
            speedTree.GetTreeSize(ref originalSize, ref variance);
            speedTree.OriginalSize = originalSize;
            speedTree.SetTreeSize(size, sizeVariance);

            treeTextures = speedTree.Textures;

            // make sure the tree doesn't have too many leaf texture groups
            Debug.Assert(treeTextures.LeafTextureFilenames.Length <= 3);

            // for trees with 3 leaf textures, reduce the number of rocking groups to 2
            // (from the default of 3), so that we don't overflow the number of available shader
            // param registers
            if (treeTextures.LeafTextureFilenames.Length == 3)
            {
                speedTree.NumLeafRockingGroups = 2;
            }

            speedTree.Compute(SpeedTreeUtil.ToSpeedTree(Matrix4.Identity), 1, true);

            speedTree.TreePosition = SpeedTreeUtil.ToSpeedTree(Vector3.Zero);

            // set lod limits
            speedTree.SetLodLimits(nearLOD, farLOD);

            // create the geometry object
            geometry = new TreeGeometry();

            //
            // Setup branches
            //

            // create the render operation
            branchRenderOp = new RenderOperation();
            branchRenderOp.operationType = OperationType.TriangleStrip;
            branchRenderOp.useIndices = true;

            // set up the material.
            branchMaterial = SetupTreeMaterial("SpeedTree/Branch", treeTextures.BranchTextureFilename, treeTextures.SelfShadowFilename, GenerateNormalMapTextureName(treeTextures.BranchTextureFilename), speedTree.BranchMaterial, !normalMapped, branchTechnique);

            // get number of branch LODs
            uint nBranchLODs = speedTree.NumBranchLodLevels;

            // allocate branch buffers
            branchVertexBuffers = new VertexData[nBranchLODs];
            branchIndexBuffers = new IndexData[nBranchLODs];

            for (short i = 0; i < nBranchLODs; i++)
            {
                // set up the vertex and index buffers for the branch geometry
                speedTree.GetGeometry(geometry, SpeedTreeWrapper.GeometryFlags.BranchGeometry, i, -1, -1);
                BuildIndexedBuffer(geometry.Branches, true, out branchVertexBuffers[i], out branchIndexBuffers[i]);
            }
            //
            // Setup fronds
            //

            // create the render operation
            frondRenderOp = new RenderOperation();
            frondRenderOp.operationType = OperationType.TriangleStrip;
            frondRenderOp.useIndices = true;

            // set up the material
            frondMaterial = SetupTreeMaterial("SpeedTree/Frond", treeTextures.CompositeFilename, treeTextures.SelfShadowFilename, null, speedTree.FrondMaterial, true, 0);

            uint nFrondLODs = speedTree.NumFrondLodLevels;

            // allocate frond buffer arrays
            frondVertexBuffers = new VertexData[nFrondLODs];
            frondIndexBuffers = new IndexData[nFrondLODs];

            for ( short i = 0; i < nFrondLODs; i++ )
            {
                // build the frond geometry for each LOD
                speedTree.GetGeometry(geometry, SpeedTreeWrapper.GeometryFlags.FrondGeometry, -1, i, -1);
                BuildIndexedBuffer(geometry.Fronds, false, out frondVertexBuffers[i], out frondIndexBuffers[i]);
            }

            //
            // Setup Leaves
            //

            TreeCamera saveCam = SpeedTreeWrapper.Camera;

            TreeCamera treeCamera = new TreeCamera();
            treeCamera.position = SpeedTreeUtil.ToSpeedTree(Vector3.Zero);
            treeCamera.direction = SpeedTreeUtil.ToSpeedTree(new Vector3(1,0,0));
            SpeedTreeWrapper.Camera = treeCamera;

            // set up render ops
            leaf0RenderOp = new RenderOperation();
            leaf0RenderOp.operationType = OperationType.TriangleList;
            leaf0RenderOp.useIndices = true;

            leaf1RenderOp = new RenderOperation();
            leaf1RenderOp.operationType = OperationType.TriangleList;
            leaf1RenderOp.useIndices = true;

            // set up the material
            leafMaterial = SetupTreeMaterial("SpeedTree/Leaf", treeTextures.CompositeFilename, null, null, speedTree.LeafMaterial, true, 0);

            uint nLeafLODs = speedTree.NumLeafLodLevels;

            // allocate leaf buffer arrays
            leafVertexBuffers = new VertexData[nLeafLODs];
            leafIndexBuffers = new IndexData[nLeafLODs];

            float [] lodLeafAdjust = speedTree.LeafLodSizeAdjustments;

            for ( short i = 0; i < nLeafLODs; i++ )
            {
                // build the leaf geometry for each LOD
                speedTree.GetGeometry(geometry, SpeedTreeWrapper.GeometryFlags.LeafGeometry, -1, -1, i);
                BuildLeafBuffer(geometry.Leaves0, lodLeafAdjust[i], out leafVertexBuffers[i], out leafIndexBuffers[i]);
            }

            // restore the camera afte getting leaf buffers
            SpeedTreeWrapper.Camera = saveCam;

            bounds = new AxisAlignedBox();

            // build all the trees and accumulate bounds
            foreach (Vector3 loc in locations)
            {
                SpeedTreeWrapper treeInstance = speedTree.MakeInstance();
                treeInstance.OriginalSize = originalSize;
                Tree t = new Tree(this, treeInstance, loc);

                bounds.Merge(t.Bounds);

                trees.Add(t);
            }

            boundingRadius = (bounds.Maximum - bounds.Minimum).Length / 2;

            // create the buckets
            branchBuckets = new Dictionary<int, List<Tree>>[nBranchLODs];
            frondBuckets = new Dictionary<int, List<Tree>>[nFrondLODs];
            leafBuckets = new Dictionary<int, List<Tree>>[nLeafLODs];
            billboardBucket = new Dictionary<int, List<Tree>>[1];

            // initialize the bucket dictionaries
            for (int i = 0; i < nBranchLODs; i++)
            {
                branchBuckets[i] = new Dictionary<int, List<Tree>>();
            }
            for (int i = 0; i < nFrondLODs; i++)
            {
                frondBuckets[i] = new Dictionary<int, List<Tree>>();
            }
            for (int i = 0; i < nLeafLODs; i++)
            {
                leafBuckets[i] = new Dictionary<int, List<Tree>>();
            }
            billboardBucket[0] = new Dictionary<int, List<Tree>>();
            allGroups.Add(this);
        }
        public void RenderLeaves(RenderSystem targetRenderSystem, int positionParamIndex, Tree t)
        {
            if (meterRenderingOfTrees)
            {
                renderLeavesMeter.Enter();
            }

            // set the position register in the hardware
            positionParameters.SetConstant(positionParamIndex, t.Location.x, t.Location.y, t.Location.z, 0);
            targetRenderSystem.BindGpuProgramParameters(GpuProgramType.Vertex, positionParameters);

            if (t.Leaf0RenderArgs.Active)
            {
                targetRenderSystem.SetAlphaRejectSettings(CompareFunction.Greater, (byte)t.Leaf0RenderArgs.AlphaTestValue);
                int lod = t.Leaf0RenderArgs.LOD;
                leaf0RenderOp.vertexData = leafVertexBuffers[lod];
                leaf0RenderOp.indexData = leafIndexBuffers[lod];

                if (leaf0RenderOp.vertexData != null)
                {
                    targetRenderSystem.Render(leaf0RenderOp);
                }
            }
            if (t.Leaf1RenderArgs.Active)
            {
                targetRenderSystem.SetAlphaRejectSettings(CompareFunction.Greater, (byte)t.Leaf1RenderArgs.AlphaTestValue);

                int lod = t.Leaf1RenderArgs.LOD;
                leaf1RenderOp.vertexData = leafVertexBuffers[lod];
                leaf1RenderOp.indexData = leafIndexBuffers[lod];
                if (leaf1RenderOp.vertexData != null)
                {
                    targetRenderSystem.Render(leaf1RenderOp);
                }
            }
            if (meterRenderingOfTrees)
            {
                renderLeavesMeter.Exit();
            }
        }
        protected void AddToBucket(Dictionary<int, List<Tree>>[] buckets, TreeRenderArgs args, Tree t)
        {
            if (args.Active)
            {
                int lod = args.LOD;
                int alpha = args.AlphaTestValue;

                if (!buckets[lod].ContainsKey(alpha))
                {
                    buckets[lod][alpha] = new List<Tree>();
                }
                buckets[lod][alpha].Add(t);
            }
        }
        public void RenderBranch(RenderSystem targetRenderSystem, int positionParamIndex, Tree t)
        {
            if (meterRenderingOfTrees)
            {
                renderBranchMeter.Enter();
            }

            int lod = t.BranchRenderArgs.LOD;

            if ((branchVertexBuffers[lod] != null) && (branchIndexBuffers[lod] != null))
            {

                targetRenderSystem.SetAlphaRejectSettings(CompareFunction.Greater, (byte)t.BranchRenderArgs.AlphaTestValue);

                // set the position register in the hardware
                positionParameters.SetConstant(positionParamIndex, t.Location.x, t.Location.y, t.Location.z, 0);
                targetRenderSystem.BindGpuProgramParameters(GpuProgramType.Vertex, positionParameters);

                branchRenderOp.vertexData = branchVertexBuffers[lod];
                branchRenderOp.indexData = branchIndexBuffers[lod];
                targetRenderSystem.Render(branchRenderOp);
            }
            if (meterRenderingOfTrees)
            {
                renderBranchMeter.Exit();
            }
        }