/// <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()); } }