Beispiel #1
0
        public Tree(TreeGroup group, SpeedTreeWrapper speedTree, Vector3 location)
        {
            this.group    = group;
            this.location = location;

            this.speedTree = speedTree;

            billboard0 = new float[20];
            billboard1 = new float[20];

            // set location for the instance
            speedTree.TreePosition = SpeedTreeUtil.ToSpeedTree(location);

            // set bounding box
            AxisAlignedBox stbox = SpeedTreeUtil.FromSpeedTree(speedTree.BoundingBox);

            this.bounds = new AxisAlignedBox(stbox.Minimum + location, stbox.Maximum + location);
        }
        public Tree(TreeGroup group, SpeedTreeWrapper speedTree, Vector3 location)
        {
            this.group = group;
            this.location = location;

            this.speedTree = speedTree;

            billboard0 = new float[20];
            billboard1 = new float[20];

            // set location for the instance
            speedTree.TreePosition = SpeedTreeUtil.ToSpeedTree(location);

            // set bounding box
            AxisAlignedBox stbox = SpeedTreeUtil.FromSpeedTree(speedTree.BoundingBox);

            this.bounds = new AxisAlignedBox(stbox.Minimum  + location, stbox.Maximum + location);
        }
        // This method is the callback by which the forests controlled
        // by the scene manager tell us about SpeedTrees.
        private void AddTreeObstacles(SpeedTreeWrapper tree)
        {
            // If this tree didn't use to be in range but now is
            V3 vp = tree.TreePosition;
            Vector3 p = new Vector3(vp.x, vp.y, vp.z);
            // Find the tile in question
            int tileX, tileZ;
            WorldToTileCoords(p, out tileX, out tileZ);
            bool oir = InRange(tileXCenter, tileZCenter, tileX, tileZ);
            bool nir = InRange(newTileXCenter, newTileZCenter, tileX, tileZ);
            //             if (MO.DoLog)
            //                 MO.Log(String.Format("For tree at {0}, testing !InRange({1},{2},{3},{4}) = {5} && InRange({6},{7},{8},{9}) = {10}",
            //                                      MO.MeterString(p),tileXCenter, tileZCenter, tileX, tileZ, MO.Bool(!oir),
            //                                      newTileXCenter, newTileZCenter, tileX, tileZ, MO.Bool(nir)));
            if (!oir && nir) {
                int tX = TileToArrayIndex(tileX, newTileXCenter);
                int tZ = TileToArrayIndex(tileZ, newTileZCenter);
                uint count = tree.CollisionObjectCount;
                long handle = ComposeHandle(tileX, tileZ);
                CollisionShape shape = null;
                if (MO.DoLog) {
                    MO.Log(string.Format("Adding tree at {0}, tiles[{1},{2}] = {3}, tile coords[{4},{5}], obj. new count {6}",
                                      MO.MeterString(p), tX, tZ, tiles[tX,tZ], tileX, tileZ, count));
                    MO.Log(string.Format("Handle {0}, oldcenter {1}, newcenter {2}",
                                         MO.HandleString(handle), MO.MeterString(tileWorldCenter), MO.MeterString(newTileWorldCenter)));
                }
                float size = 0f;
                float variance = 0f;
                tree.GetTreeSize(ref size, ref variance);
                float scaleFactor = size / tree.OriginalSize;
                for (uint i=0; i<count; i++) {
                    TreeCollisionObject tco = tree.CollisionObject(i);
                    Vector3 cp = new Vector3(tco.position.x, tco.position.y, tco.position.z) * scaleFactor + p;
                    Vector3 cd = new Vector3(tco.dimensions.x, tco.dimensions.y, tco.dimensions.z) * scaleFactor;
                    switch ((CollisionObjectType)tco.type) {
                    case CollisionObjectType.ColSphere:
                        shape = new CollisionSphere(cp, cd.x);
                        break;
                    case CollisionObjectType.ColCylinder:
                        // We treat it as a capsule, but we raise the
                        // capsule up by the capRadius, and shorten
                        // the segment by the double the capRadius
                        Vector3 top = cp;
                        top.y += cd.y - cd.x * 2f;
                        cp.y += cd.x;
                        shape = new CollisionCapsule(cp, top, cd.x);
                        break;
                    case CollisionObjectType.ColBox:
                        Vector3 tp = cp;
                        tp.x -= cd.x * .5f;
                        tp.y -= cd.y * .5f;
                        shape = new CollisionAABB(tp, tp + cd);
                        break;
                    }
                    collisionAPI.AddCollisionShape(shape, handle);
                    tiles[tX, tZ]++;
                    objectsAdded++;

                    if (MO.DoLog) {
                        MO.Log(string.Format(" tiles[{0},{1}] = {2}, tile at [{3},{4}] after adding shape {5}",
                                          tX, tZ, tiles[tX, tZ], tileX, tileZ, shape.ToString()));
                    }
                }
            }
        }
        // This method is the callback by which the forests controlled
        // by the scene manager tell us about SpeedTrees.
        private void AddTreeObstacles(SpeedTreeWrapper tree)
        {
            // If this tree didn't use to be in range but now is
            V3      vp = tree.TreePosition;
            Vector3 p  = new Vector3(vp.x, vp.y, vp.z);
            // Find the tile in question
            int tileX, tileZ;

            WorldToTileCoords(p, out tileX, out tileZ);
            bool oir = InRange(tileXCenter, tileZCenter, tileX, tileZ);
            bool nir = InRange(newTileXCenter, newTileZCenter, tileX, tileZ);

//             if (MO.DoLog)
//                 MO.Log(String.Format("For tree at {0}, testing !InRange({1},{2},{3},{4}) = {5} && InRange({6},{7},{8},{9}) = {10}",
//                                      MO.MeterString(p),tileXCenter, tileZCenter, tileX, tileZ, MO.Bool(!oir),
//                                      newTileXCenter, newTileZCenter, tileX, tileZ, MO.Bool(nir)));
            if (!oir && nir)
            {
                int            tX     = TileToArrayIndex(tileX, newTileXCenter);
                int            tZ     = TileToArrayIndex(tileZ, newTileZCenter);
                uint           count  = tree.CollisionObjectCount;
                long           handle = ComposeHandle(tileX, tileZ);
                CollisionShape shape  = null;
                if (MO.DoLog)
                {
                    MO.Log(string.Format("Adding tree at {0}, tiles[{1},{2}] = {3}, tile coords[{4},{5}], obj. new count {6}",
                                         MO.MeterString(p), tX, tZ, tiles[tX, tZ], tileX, tileZ, count));
                    MO.Log(string.Format("Handle {0}, oldcenter {1}, newcenter {2}",
                                         MO.HandleString(handle), MO.MeterString(tileWorldCenter), MO.MeterString(newTileWorldCenter)));
                }
                float size     = 0f;
                float variance = 0f;
                tree.GetTreeSize(ref size, ref variance);
                float scaleFactor = size / tree.OriginalSize;
                for (uint i = 0; i < count; i++)
                {
                    TreeCollisionObject tco = tree.CollisionObject(i);
                    Vector3             cp  = new Vector3(tco.position.x, tco.position.y, tco.position.z) * scaleFactor + p;
                    Vector3             cd  = new Vector3(tco.dimensions.x, tco.dimensions.y, tco.dimensions.z) * scaleFactor;
                    switch ((CollisionObjectType)tco.type)
                    {
                    case CollisionObjectType.ColSphere:
                        shape = new CollisionSphere(cp, cd.x);
                        break;

                    case CollisionObjectType.ColCylinder:
                        // We treat it as a capsule, but we raise the
                        // capsule up by the capRadius, and shorten
                        // the segment by the double the capRadius
                        Vector3 top = cp;
                        top.y += cd.y - cd.x * 2f;
                        cp.y  += cd.x;
                        shape  = new CollisionCapsule(cp, top, cd.x);
                        break;

                    case CollisionObjectType.ColBox:
                        Vector3 tp = cp;
                        tp.x -= cd.x * .5f;
                        tp.y -= cd.y * .5f;
                        shape = new CollisionAABB(tp, tp + cd);
                        break;
                    }
                    collisionAPI.AddCollisionShape(shape, handle);
                    tiles[tX, tZ]++;
                    objectsAdded++;

                    if (MO.DoLog)
                    {
                        MO.Log(string.Format(" tiles[{0},{1}] = {2}, tile at [{3},{4}] after adding shape {5}",
                                             tX, tZ, tiles[tX, tZ], tileX, tileZ, shape.ToString()));
                    }
                }
            }
        }
        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);
        }