建BSP 树分割图形

//从“列表”中构建一个BSP树。当调用现有树时,新多边形被过滤到树的底部,
// 并在那里成为新的节点
 public void Build(List<CSG_Polygon> list)//建BSP树
		{
			if (list.Count < 1)//判断是否有图形
				return;

			if (this.plane == null || !this.plane.Valid())
			{
				this.plane = new CSG_Plane();
				this.plane.normal = list[0].plane.normal;
				this.plane.w = list[0].plane.w;
			}


			if(this.polygons == null)
				this.polygons = new List<CSG_Polygon>();

			List<CSG_Polygon> list_front = new List<CSG_Polygon>();//正面
			List<CSG_Polygon> list_back = new List<CSG_Polygon>();//背面

			for (int i = 0; i < list.Count; i++) 
			{
				this.plane.SplitPolygon(list[i], this.polygons, this.polygons, list_front, list_back);
			}

			if (list_front.Count > 0) 
			{
				if (this.front == null)
					this.front = new CSG_Node();

				this.front.Build(list_front);//从正面做一个BSP树
			}

			if (list_back.Count > 0) 
			{
				if (this.back == null)
					this.back = new CSG_Node();

				this.back.Build(list_back);//从背面做一棵树
			}
		}

	public bool Valid()
		{
			return normal.magnitude > 0f;
		}
/*如果需要的话,按这个平面分割“多边形”,然后将多边形或多边形片段放入适当的列表中。
根据共面多边形相对于这个平面的方向,它们可以分为“共面前”或“共面后”*/
	 public void SplitPolygon(CSG_Polygon polygon, List<CSG_Polygon> coplanarFront, List<CSG_Polygon> coplanarBack, List<CSG_Polygon> front, List<CSG_Polygon> back)
		{
			
			EPolygonType polygonType = 0;
			List<EPolygonType> types = new List<EPolygonType>();//节点类型数组

			for (int i = 0; i < polygon.vertices.Count; i++) 
			{
				float t = Vector3.Dot(this.normal, polygon.vertices[i].position) - this.w;
				/*
				enum EPolygonType
				{
				Coplanar 	= 0,//共面
				Front 		= 1,//前面
				Back 		= 2,//后面
				Spanning 	= 3 		/// 3 is Front | Back - not a separate entry
				};
				*/
				EPolygonType type = (t < -CSG.EPSILON) ? EPolygonType.Back : ((t > CSG.EPSILON) ? EPolygonType.Front : EPolygonType.Coplanar);//判断这个节点的类型
				polygonType |= type;
				types.Add(type);
			}

			// 将多边形放入正确的列表中,必要时将其分割。
			switch (polygonType) 
			{
				case EPolygonType.Coplanar:
				{
					if ( Vector3.Dot(this.normal, polygon.plane.normal) > 0)
						coplanarFront.Add(polygon);
					else 
						coplanarBack.Add(polygon);
				}
				break;

				case EPolygonType.Front:
				{
					front.Add(polygon);
				}
				break;
			
				case EPolygonType.Back:
				{
					back.Add(polygon);
				}
				break;
			
			//再次分类
				case EPolygonType.Spanning:
				{
					List<CSG_Vertex> f = new List<CSG_Vertex>();//前面
					List<CSG_Vertex> b = new List<CSG_Vertex>();//背面

					for (int i = 0; i < polygon.vertices.Count; i++) 
					{
						int j = (i + 1) % polygon.vertices.Count;

						EPolygonType ti = types[i], tj = types[j];

						CSG_Vertex vi = polygon.vertices[i], vj = polygon.vertices[j];

						if (ti != EPolygonType.Back)
						{
							f.Add(vi);
						}
						
						if (ti != EPolygonType.Front)
						{
							b.Add(vi);
						}

						if ((ti | tj) == EPolygonType.Spanning) 
						{
							float t = (this.w - Vector3.Dot(this.normal, vi.position)) / Vector3.Dot(this.normal, vj.position - vi.position);
							
							CSG_Vertex v = CSG_Vertex.Interpolate(vi, vj, t);

							f.Add(v);
							b.Add(v);
						}
					}

					//三点构成一个面
					if (f.Count >= 3)
					{
						front.Add( new CSG_Polygon(f) );
					}

					if (b.Count >= 3)
					{
						back.Add( new CSG_Polygon(b) );
					}
				}
				break;
			}
		}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值