Example #1
0
    /// <summary>
    /// 构建八叉树
    /// </summary>
    public static Octree Build(TreeModel treeModel)
    {
        GameObject root = treeModel.TreeModelInstance;     //获取根节点表示的模型

        if (root == null)
        {
            return(null);
        }

        /*
         * 添加包含整个植物的包围盒
         * 八叉树则以该包围盒为根节点进行构建
         */
        Mesh.AddBoxColliderInParent(root);
        Bounds rootBounds = root.GetComponent <Collider>().bounds;

        if (IsEmpty(rootBounds))
        {
            return(null);
        }

        List <Triangle> triangles = GameObjectOperation.GetTreeTriangles(treeModel);

        if (triangles == null || triangles.Count == 0)
        {
            return(null);
        }

        return(new Octree(rootBounds.center, rootBounds.size, GameObjectOperation.GetTreeTriangles(treeModel), 5));
    }
    /// <summary>
    /// 模拟天空散射
    /// </summary>
    /// <param name="SolarDayAngle_Deg">太阳日角</param>
    /// <param name="SolarAltitude_Deg">太阳高度角</param>
    /// <param name="StartHour">开始的时间</param>
    /// <param name="EndHour">结束的时间</param>
    /// <param name="_Octree">八叉树</param>
    /// <param name="LatitudeNum">纬度方向的剖分个数</param>
    /// <param name="LongtitudeNum">经度度方向的剖分个数</param>
    public static void ScatterLightSimulation(TreeModel treeModel, double SolarDayAngle_Rad, double SolarAltitude_Deg, double StartHour, double EndHour, Octree _Octree, int LatitudeNum, int LongtitudeNum)
    {
        Triangle[] TreeTriangles = GameObjectOperation.GetTreeTriangles(treeModel).ToArray();                              //获取所有的三角面片

        double _ScatterIrradiance = ScatterIrradiance(SolarDayAngle_Rad, SolarAltitude_Deg, _Octree.Root.Bounds.center.y); //总散射辐射度

        LightCastHemisphere LightHemisphere = null;

        for (int i = 0; i < TreeTriangles.Length; i++)
        {
            if (TreeTriangles[i].Type != OrganType.Leaf)
            {
                continue;                                           //非叶片,无需计算散射辐射
            }

            /*
             * 优化
             * 限定天穹半球的大小
             * 每次三角面片,天穹半球跟随三角面片移动,无需重新计算
             */
            if (LightHemisphere == null)
            {
                LightHemisphere = new LightCastHemisphere(TreeTriangles[i].Center, _Octree.Root.Bounds);
            }
            else
            {
                LightHemisphere.MoveTo(TreeTriangles[i].Center);
            }

            /*
             * 通过天穹半球计算出天空散射透过率
             * 该面片上的平均散射辐射度(W / m^2) = 天空散射透过率 * 总散射辐射度
             * 该面片上的总辐射度(W) = 平均散射辐射度 * 该面片的面积
             * 注意:因为存在透明的纹理,因此需要再得到整个叶片模型的散射能量的基础上,再乘以非透明的比例,才能得到真正的散射能量
             */
            LeafIndex _LeafIndex = TreeTriangles[i].Index as LeafIndex;

            _LeafIndex.ModelScatterEnergy += (float)(LightHemisphere.GetSkyTransmissivity(LongtitudeNum, LatitudeNum, TreeTriangles, i) * _ScatterIrradiance * TreeTriangles[i].Area());
        }
    }