示例#1
0
	public static bool MergeContours(ref VoxelContour ca, ref VoxelContour cb, int ia, int ib) {
		
		int maxVerts = ca.nverts + cb.nverts + 2;
		int[] verts = new int[maxVerts*4];
		
		//if (!verts)
		//	return false;
	
		int nv = 0;
	
		// Copy contour A.
		for (int i = 0; i <= ca.nverts; i++)
		{
			int dst = nv*4;
			int src = ((ia+i) % ca.nverts)*4;
			verts[dst+0] = ca.verts[src+0];
			verts[dst+1] = ca.verts[src+1];
			verts[dst+2] = ca.verts[src+2];
			verts[dst+3] = ca.verts[src+3];
			nv++;
		}
	
		// Copy contour B
		for (int i = 0; i <= cb.nverts; i++)
		{
			int dst = nv*4;
			int src = ((ib+i) % cb.nverts)*4;
			verts[dst+0] = cb.verts[src+0];
			verts[dst+1] = cb.verts[src+1];
			verts[dst+2] = cb.verts[src+2];
			verts[dst+3] = cb.verts[src+3];
			nv++;
		}
		
		//rcFree(ca.verts);
		ca.verts = verts;
		ca.nverts = nv;
	
		//rcFree(cb.verts);
		cb.verts = new int[0];
		cb.nverts = 0;
		
		return true;
	}
示例#2
0
	public void BuildContours (float maxError, int maxEdgeLength, VoxelContourSet cset, int buildFlags) {
		
		int w = voxelArea.width;
		int d = voxelArea.depth;
		
		int wd = w*d;
		
		//cset.bounds = voxelArea.bounds;
		
		int maxContours = Mathf.Max (8/*Max Regions*/,8);
		
		//cset.conts = new VoxelContour[maxContours];
		List<VoxelContour> contours = new List<VoxelContour>(maxContours);
		
		//cset.nconts = 0;
		
		int[] flags = new int[voxelArea.compactSpans.Length];
		
		// Mark boundaries. (@?)
		for (int z=0;z < wd;z += voxelArea.width) {
			for (int x=0;x < voxelArea.width;x++) {
				
				CompactVoxelCell c = voxelArea.compactCells[x+z];
				
				for (int i= (int)c.index, ci = (int)(c.index+c.count); i < ci; i++) {
					
					int res = 0;
					CompactVoxelSpan s = voxelArea.compactSpans[i];
					
					if (s.reg == 0 || (s.reg & BorderReg) == BorderReg) {
						flags[i] = 0;
						continue;
					}
					
					for (int dir=0;dir < 4; dir++) {
						int r = 0;
						
						if (s.GetConnection (dir) != NotConnected) {
							int nx = x + voxelArea.DirectionX[dir];
							int nz = z + voxelArea.DirectionZ[dir];
							
							int ni = (int)voxelArea.compactCells[nx+nz].index + s.GetConnection (dir);
							r = voxelArea.compactSpans[ni].reg;
							
							
						}
						
						//@TODO - Why isn't this inside the previous IF
						if (r == s.reg) {
							res |= (1 << dir);
							
						}
					}
					
					//Inverse, mark non connected edges.
					flags[i] = res ^ 0xf;
						
				}
				
			}
		}
		
		
		List<int> verts = new List<int> (256);
		List<int> simplified = new List<int> (64);
		
		for (int z=0;z < wd;z += voxelArea.width) {
			for (int x=0;x < voxelArea.width;x++) {
				
				CompactVoxelCell c = voxelArea.compactCells[x+z];
				
				for (int i= (int)c.index, ci = (int)(c.index+c.count); i < ci; i++) {
					
					//CompactVoxelSpan s = voxelArea.compactSpans[i];
					
					if (flags[i] == 0 || flags[i] == 0xf)
					{
						flags[i] = 0;
						continue;
					}
					
					int reg = voxelArea.compactSpans[i].reg;
					
					if (reg == 0 || (reg & BorderReg) == BorderReg) {
						continue;
					}
					
					int area = voxelArea.areaTypes[i];
					
					verts.Clear ();
					simplified.Clear ();
					
					WalkContour(x, z, i, flags, verts);
					
					SimplifyContour(verts, simplified, maxError, maxEdgeLength, buildFlags);
					RemoveDegenerateSegments (simplified);
					
					VoxelContour contour = new VoxelContour ();
					contour.verts = simplified.ToArray ();
					contour.rverts = verts.ToArray ();
					contour.nverts = simplified.Count/4;
					contour.reg = reg;
					contour.area = area;
					
					contours.Add (contour);
					
					#if ASTARDEBUG
					for (int q=0, j = (simplified.Count/4)-1;q<(simplified.Count/4);j=q, q++) {
			
						int i4 = q*4;
						int j4 = j*4;
						
						Vector3 p1 = Vector3.Scale (
						new Vector3 (
							simplified[i4+0],
							simplified[i4+1],
							(simplified[i4+2]/(float)voxelArea.width)
						),
						CellScale)
						+voxelOffset;
						
						Vector3 p2 = Vector3.Scale (
						new Vector3 (
							simplified[j4+0],
							simplified[j4+1],
							(simplified[j4+2]/(float)voxelArea.width)
						)
						,CellScale)
						+voxelOffset;
						
						
						if (CalcAreaOfPolygon2D(contour.verts, contour.nverts) > 0) {
							Debug.DrawLine (p1,p2,Mathfx.IntToColor (reg,0.5F));
						} else {
							Debug.DrawLine (p1,p2,Color.red);
							
						}
						
					}
					#endif
				}
			}
		}
		
		// Check and merge droppings.
		// Sometimes the previous algorithms can fail and create several contours
		// per area. This pass will try to merge the holes into the main region.
		for (int i = 0; i < contours.Count; i++)
		{
			VoxelContour cont = contours[i];
			// Check if the contour is would backwards.
			if (CalcAreaOfPolygon2D(cont.verts, cont.nverts) < 0)
			{
				// Find another contour which has the same region ID.
				int mergeIdx = -1;
				for (int j = 0; j < contours.Count; j++)
				{
					if (i == j) continue;
					if (contours[j].nverts > 0 && contours[j].reg == cont.reg)
					{
						// Make sure the polygon is correctly oriented.
						if (CalcAreaOfPolygon2D(contours[j].verts, contours[j].nverts) > 0)
						{
							mergeIdx = j;
							break;
						}
					}
				}
				if (mergeIdx == -1)
				{
					Debug.LogError ("rcBuildContours: Could not find merge target for bad contour "+i+".");
				}
				else
				{
					Debug.LogWarning ("Fixing contour");
					VoxelContour mcont = contours[mergeIdx];
					// Merge by closest points.
					int ia = 0, ib = 0;
					GetClosestIndices(mcont.verts, mcont.nverts, cont.verts, cont.nverts, ref ia, ref ib);
					
					if (ia == -1 || ib == -1)
					{
						Debug.LogWarning ("rcBuildContours: Failed to find merge points for "+i+" and "+mergeIdx+".");
						continue;
					}
					
					int p4 = ia*4;
					int p42 = ib*4;
						
					Vector3 p12 = Vector3.Scale (
						new Vector3 (
							mcont.verts[p4+0],
							mcont.verts[p4+1],
							(mcont.verts[p4+2]/(float)voxelArea.width)
						),
						CellScale)
						+voxelOffset;
						
						Vector3 p22 = Vector3.Scale (
						new Vector3 (
							cont.verts[p42+0],
							cont.verts[p42+1],
							(cont.verts[p42+2]/(float)voxelArea.width)
						)
						,CellScale)
						+voxelOffset;
					
					Debug.DrawLine (p12,p22,Color.green);
					
					if (!MergeContours(ref mcont, ref cont, ia, ib))
					{
						Debug.LogWarning ("rcBuildContours: Failed to merge contours "+i+" and "+mergeIdx+".");
						continue;
					}
					
					contours[mergeIdx] = mcont;
					contours[i] = cont;
					
					#if ASTARDEBUG
					Debug.Log (mcont.nverts);
					
					for (int q=0, j = (mcont.nverts)-1;q<(mcont.nverts);j=q, q++) {
						int i4 = q*4;
						int j4 = j*4;
						
						Vector3 p1 = Vector3.Scale (
						new Vector3 (
							mcont.verts[i4+0],
							mcont.verts[i4+1],
							(mcont.verts[i4+2]/(float)voxelArea.width)
						),
						CellScale)
						+voxelOffset;
						
						Vector3 p2 = Vector3.Scale (
						new Vector3 (
							mcont.verts[j4+0],
							mcont.verts[j4+1],
							(mcont.verts[j4+2]/(float)voxelArea.width)
						)
						,CellScale)
						+voxelOffset;
						
						Debug.DrawLine (p1,p2,Color.red);
					//}
					}
					#endif
				}
			}
		}
	
		cset.conts = contours.ToArray ();
	}