Пример #1
0
        /**
         *	\brief Cycles through a mesh and returns a pb_IntArray[] of
         *	triangles that point to the same point in world space.
         *	@param _mesh The mesh to examine.
         *	\sa pb_IntArray
         *	\notes pbIntArray exists because Unity cannot serialize jagged arrays.
         *	\returns A pb_IntArray[] (basically just an int[][] with some added functionality).
         */
        public static pb_IntArray[] ExtractSharedIndices(Vector3[] v)
        {
            Dictionary <pb_IntVec3, List <int> > sorted = new Dictionary <pb_IntVec3, List <int> >();

            List <int> ind;

            for (int i = 0; i < v.Length; i++)
            {
                if (sorted.TryGetValue(v[i], out ind))
                {
                    ind.Add(i);
                }
                else
                {
                    sorted.Add(new pb_IntVec3(v[i]), new List <int>()
                    {
                        i
                    });
                }
            }

            pb_IntArray[] share = new pb_IntArray[sorted.Count];

            int t = 0;

            foreach (KeyValuePair <pb_IntVec3, List <int> > kvp in sorted)
            {
                share[t++] = new pb_IntArray(kvp.Value.ToArray());
            }

            return(share);
        }
Пример #2
0
 public static pb_IntArray[] ToPbIntArray(this List <List <int> > val)
 {
     pb_IntArray[] arr = new pb_IntArray[val.Count];
     for (int i = 0; i < arr.Length; i++)
     {
         arr[i] = (pb_IntArray)val[i].ToArray();
     }
     return(arr);
 }
Пример #3
0
 /**
  * Convert a jagged int array to a pb_IntArray.
  */
 public static pb_IntArray[] ToPbIntArray(this int[][] val)
 {
     pb_IntArray[] arr = new pb_IntArray[val.Length];
     for (int i = 0; i < arr.Length; i++)
     {
         arr[i] = (pb_IntArray)val[i];
     }
     return(arr);
 }
Пример #4
0
        /**
         *	Associates all passed indices with a single shared index.  Does not perfrom any additional operations
         *	to repair triangle structure or vertex placement.
         */
        public static int MergeSharedIndices(ref pb_IntArray[] sharedIndices, int[] indices)
        {
            if (indices.Length < 2)
            {
                return(-1);
            }
            if (sharedIndices == null)
            {
                sharedIndices = new pb_IntArray[1] {
                    (pb_IntArray)indices
                };
                return(0);
            }

            List <int> used           = new List <int>();
            List <int> newSharedIndex = new List <int>();

            // Create a new int[] composed of all indices in shared selection
            for (int i = 0; i < indices.Length; i++)
            {
                int si = sharedIndices.IndexOf(indices[i]);
                if (!used.Contains(si))
                {
                    if (si > -1)
                    {
                        newSharedIndex.AddRange(sharedIndices[si].array);
                        used.Add(si);
                    }
                    else
                    {
                        newSharedIndex.Add(indices[i]);
                    }
                }
            }

            // Now remove the old entries
            int rebuiltSharedIndexLength = sharedIndices.Length - used.Count;

            pb_IntArray[] rebuild = new pb_IntArray[rebuiltSharedIndexLength];

            int n = 0;

            for (int i = 0; i < sharedIndices.Length; i++)
            {
                if (!used.Contains(i))
                {
                    rebuild[n++] = sharedIndices[i];
                }
            }

            sharedIndices = rebuild.Add(new pb_IntArray(newSharedIndex.ToArray()));
            // SetSharedIndices( rebuild.Add( new pb_IntArray(newSharedIndex.ToArray()) ) );

            return(sharedIndices.Length - 1);
        }
Пример #5
0
		public static void Rebuild()
		{
			pb_Object[] pbObjs = (pb_Object[])GameObject.FindObjectsOfType(typeof(pb_Object));
			foreach(pb_Object pb in pbObjs)
			{
				pb_IntArray[] val = pb.sharedIndices;
					
				List<int> empty = new List<int>();

				for(int i = 0; i < val.Length; i++)
					if(val[i].IsEmpty())
						empty.Add(i);
				
				pb_IntArray[] trimmed = new pb_IntArray[val.Length-empty.Count];
				
				int n = 0;
				for(int i = 0; i < trimmed.Length; i++)
					if(!empty.Contains(i))
						trimmed[n++] = val[i];
							
				pb.SetSharedIndices( trimmed );
			}
		}
	/**
	 * Sets the internal sharedIndices cache.  Also takes care of refreshing the uniqueIndices cache for you.
	 */
	public void SetSharedIndices(pb_IntArray[] si)
	{
		_sharedIndices = si;
		RefreshUniqueIndices();
	}
	public static void RemoveEmptyOrNull(ref pb_IntArray[] val)
	{
		List<pb_IntArray> valid = new List<pb_IntArray>();
		foreach(pb_IntArray par in val)
		{
			if(par != null && !par.IsEmpty())
				valid.Add(par);
		}
		val = valid.ToArray();
	}
	/**
	 *	\brief Removes the specified indices from the array, and shifts all values 
	 *	down to account for removal in the vertex array.  Only use when deleting
	 *	faces or vertices.  For general moving around and modification of shared 
	 *	index array, use #RemoveValuesAtIndex.
	 */
	public static void RemoveValuesAndShift(ref pb_IntArray[] sharedIndices, int[] remove)
	{
		// MUST BE DISTINCT
		remove = remove.ToDistinctArray();

		// remove face indices from all shared indices caches
		for(int i = 0; i < sharedIndices.Length; i++)
		{
			for(int n = 0; n < remove.Length; n++)
			{
				int ind = System.Array.IndexOf(sharedIndices[i], remove[n]);

				if(ind > -1)
					sharedIndices[i].array = sharedIndices[i].array.RemoveAt(ind);
			}
		}

		// Remove empty or null entries caused by shifting around all them indices
		pb_IntArray.RemoveEmptyOrNull(ref sharedIndices);
		
		// now cycle through and shift indices
		for(int i = 0; i < sharedIndices.Length; i++)
		{
			for(int n = 0; n < sharedIndices[i].Length; n++)
			{
				int ind = sharedIndices[i][n];
				int sub = 0;

				// use a count and subtract at end because indices aren't guaranteed to be in order.
				// ex, 9, 8, 7 would only sub 1 if we just did rm < ind; ind--
				foreach(int rm in remove)
				{
					if(rm < ind)
						sub++;
				}
				sharedIndices[i][n] -= sub;
			}
		}
	}	
	/**
	 * Adds a range of values to the array at index.
	 */
	public static int AddRangeAtIndex(ref pb_IntArray[] sharedIndices, int sharedIndex, int[] indices)
	{
		if(sharedIndex > -1)
			sharedIndices[sharedIndex].array = sharedIndices[sharedIndex].array.AddRange(indices);
		else
			sharedIndices = (pb_IntArray[])sharedIndices.Add( new pb_IntArray(indices) );
		
		return sharedIndex > -1 ? sharedIndex : sharedIndices.Length-1;
	}
	/**
	 *	Associates indices with a single shared index.  Does not perfrom any additional operations 
	 *	to repair triangle structure or vertex placement.
	 */
	public static void MergeSharedIndices(ref pb_IntArray[] sharedIndices, int a, int b)
	{
		int aIndex = sharedIndices.IndexOf(a);
		int oldBIndex = sharedIndices.IndexOf(b);
	
		pb_IntArrayUtility.AddValueAtIndex(ref sharedIndices, aIndex, b);

		int[] arr = sharedIndices[oldBIndex].array;
		sharedIndices[oldBIndex].array = arr.RemoveAt(System.Array.IndexOf(arr, b));
		pb_IntArray.RemoveEmptyOrNull(ref sharedIndices);
	}	
	/**
	 * Checks if an array contains a value and also compares shared indices using sharedIndices.
	 */
	public static int IndexOf(this int[] array, int val, pb_IntArray[] sharedIndices)
	{
		int indInShared = sharedIndices.IndexOf(val);
		if(indInShared < 0) return -1;

		int[] allValues = sharedIndices[indInShared];

		for(int i = 0; i < array.Length; i++)
			if(System.Array.IndexOf(allValues, array[i]) > -1)
				return i;

		return -1;
	}
Пример #12
0
	private void GeometryWithVerticesFacesIndices(Vector3[] v, pb_Face[] f, pb_IntArray[] s)
	{
		SetFaces(f);
		SetVertices(v);
		SetUV(new Vector2[v.Length]);

		SetSharedIndices(s);

		if(msh != null) DestroyImmediate(msh);

		// ToMesh builds the actual Mesh object
		ToMesh();
		// Refresh builds out the UV, Normal, Tangents, etc.
		Refresh();
	}
Пример #13
0
 // Copy constructor
 public pb_IntArray(pb_IntArray intArray)
 {
     array = intArray.array;
 }
Пример #14
0
  	/**
	  * \brief Creates an icosphere from a radius and subdivision count.
	  * This method does not extract shared indices, so after generating
	  * make sure to use pbVertexOps.Weldvertices() to generate them.
	  */
	public static pb_Object IcosahedronGenerator(float radius, int subdivisions)
	{
		// http://blog.andreaskahler.com/2009/06/creating-icosphere-mesh-in-code.html

		Vector3[] v = new Vector3[ICOSAHEDRON_TRIANGLES.Length];

		/**
		 * Regular Icosahedron - 12 vertices, 20 faces.
		 */
		for(int i = 0; i < ICOSAHEDRON_TRIANGLES.Length; i+=3)
		{
			v[i+0] = ICOSAHEDRON_VERTICES[ ICOSAHEDRON_TRIANGLES[i+0] ].normalized * radius;
			v[i+1] = ICOSAHEDRON_VERTICES[ ICOSAHEDRON_TRIANGLES[i+1] ].normalized * radius;
			v[i+2] = ICOSAHEDRON_VERTICES[ ICOSAHEDRON_TRIANGLES[i+2] ].normalized * radius;
		}

		/**
		 * Subdivide
		 */
		for(int i = 0; i < subdivisions; i++) {
			v = SubdivideIcosahedron(v, radius);
		}

		/**
		 * Wind faces
		 */
		pb_Face[] f = new pb_Face[v.Length/3];
		for(int i = 0; i < v.Length; i+=3) {
			f[i/3] = new pb_Face( new int[3] { i, i+1, i+2 } );
			f[i/3].manualUV = true;
		}

		GameObject _gameObject = new GameObject();	
		pb_Object pb = _gameObject.AddComponent<pb_Object>();

		pb.SetVertices(v);
		pb.SetUV(new Vector2[v.Length]);
		pb.SetFaces(f);

		pb_IntArray[] si = new pb_IntArray[v.Length];
		for(int i = 0; i < si.Length; i++)
			si[i] = new pb_IntArray(new int[] { i });

		pb.SetSharedIndices(si);

		pb.ToMesh();
		pb.Refresh();

		pb.SetName("Icosphere");

		return pb;
	}
Пример #15
0
	/**
	 *	\brief Returns a copy of the sharedIndicesUV array.
	 */
	public pb_IntArray[] GetSharedIndicesUV()
	{
		int sil = _sharedIndicesUV.Length;
		pb_IntArray[] sharedIndicesCopy = new pb_IntArray[sil];
		for(int i = 0; i < sil; i++)
		{
			int[] arr = new int[_sharedIndicesUV[i].Length];
			System.Array.Copy(_sharedIndicesUV[i].array, arr, arr.Length);
			sharedIndicesCopy[i] = new pb_IntArray(arr);
		}

		return sharedIndicesCopy;
	}
Пример #16
0
	public void SetSharedIndicesUV(pb_IntArray[] si)
	{
		_sharedIndicesUV = si;
	}
Пример #17
0
		/**
		 *	Similar to Merge vertices, expect that this method only collapses vertices within
		 *	a specified distance of one another (typically epsilon).  Returns true if any action
		 * 	was taken, false otherwise.  Outputs indices that have been welded in the @welds var.
		 */
		public static bool WeldVertices(this pb_Object pb, int[] indices, float delta, out int[] welds)
		{
			List<int> universal = pb.sharedIndices.GetUniversalIndices(indices).ToList();
			Vector3[] v = pb.vertices;

			HashSet<int> used = new HashSet<int>();
			KDTree<int> tree = new KDTree<int>(3, 48);	// dimensions (xyz), node size

			for(int i = 0; i < universal.Count; i++)
			{
				Vector3 vert = v[pb.sharedIndices[universal[i]][0]];
				tree.AddPoint( new double[] { vert.x, vert.y, vert.z }, universal[i]);
			}

			List<List<int>> groups = new List<List<int>>();

			double[] point = new double[3] { 0, 0, 0 };

			int[][] si = pb.sharedIndices.ToArray();
			for(int i = 0; i < universal.Count; i++)
			{
				if(used.Contains(universal[i]))
				{
					continue;
				}

				int tri = si[universal[i]][0];
				
				point[0] = v[tri].x;
				point[1] = v[tri].y;
				point[2] = v[tri].z;

				NearestNeighbour<int> neighborIterator = tree.NearestNeighbors( point, 64, delta );

				List<int> neighbors = new List<int>();

				while(neighborIterator.MoveNext())
				{
					if( used.Contains(neighborIterator.Current) )
						continue;
	
					used.Add( neighborIterator.Current );
					neighbors.Add( neighborIterator.Current );
				}

				used.Add( universal[i] );
				groups.Add( neighbors );
			}

			pb_IntArray[] rebuilt = new pb_IntArray[groups.Count];// + remainingCount ];
			welds = new int[groups.Count];

			for(int i = 0; i < groups.Count; i++)
			{
				rebuilt[i] = new pb_IntArray( groups[i].SelectMany(x => pb.sharedIndices[x].array).ToArray() );
				welds[i] = rebuilt[i][0];
			}

			foreach(pb_IntArray arr in rebuilt)
			{
				Vector3 avg = pb_Math.Average(pbUtil.ValuesWithIndices(v, arr.array));
				foreach(int i in arr.array)
					v[i] = avg;
			}

			pb.SetVertices(v);
			// profiler.EndSample();

			pb_IntArray[] remaining = pb.sharedIndices.Where( (val, index) => !used.Contains(index) ).ToArray();

			rebuilt = pbUtil.Concat(rebuilt, remaining);

			pb.SetSharedIndices(rebuilt);

			return true;	
		}
Пример #18
0
	/**
	 *	\brief Call this to ensure that the mesh is unique.  Basically performs a DeepCopy and assigns back to self.
	 */
	public void MakeUnique()
	{
		pb_Face[] q = new pb_Face[_faces.Length];

		for(int i = 0; i < q.Length; i++)
			q[i] = new pb_Face(_faces[i]);

		pb_IntArray[] sv = new pb_IntArray[_sharedIndices.Length];
		System.Array.Copy(_sharedIndices, sv, sv.Length);
		
		SetSharedIndices(sv);
		SetFaces(q);

		Vector3[] v = new Vector3[vertexCount];
		System.Array.Copy(_vertices, v, vertexCount);
		SetVertices(v);

		if(_uv != null && _uv.Length == vertexCount)
		{
			Vector2[] u = new Vector2[vertexCount];
			System.Array.Copy(_uv, u, vertexCount);
			SetUV(u);
		}

		msh = pbUtil.DeepCopyMesh(msh);
		
		ToMesh();
		Refresh();
	}
Пример #19
0
	/**
	 * Convert a jagged int array to a pb_IntArray.
	 */
	public static pb_IntArray[] ToPbIntArray(this int[][] val)
	{
		pb_IntArray[] arr = new pb_IntArray[val.Length];
		for(int i = 0; i < arr.Length; i++)
			arr[i] = (pb_IntArray)val[i];
		return arr;
	}
	/**
	 *	Associates all passed indices with a single shared index.  Does not perfrom any additional operations 
	 *	to repair triangle structure or vertex placement.
	 */
	public static int MergeSharedIndices(ref pb_IntArray[] sharedIndices, int[] indices)
	{	
		if(indices.Length < 2) return -1;
		if(sharedIndices == null)
		{
			sharedIndices = new pb_IntArray[1] { (pb_IntArray)indices };
			return 0;
		}

		List<int> used = new List<int>();
		List<int> newSharedIndex = new List<int>();

		// Create a new int[] composed of all indices in shared selection
		for(int i = 0; i < indices.Length; i++)
		{
			int si = sharedIndices.IndexOf(indices[i]);
			if(!used.Contains(si))
			{
				if( si > -1 )
				{
					newSharedIndex.AddRange( sharedIndices[si].array );
					used.Add(si);
				}
				else
				{
					newSharedIndex.Add( indices[i] );
				}
				
			}
		}

		// Now remove the old entries
		int rebuiltSharedIndexLength = sharedIndices.Length - used.Count;
		pb_IntArray[] rebuild = new pb_IntArray[rebuiltSharedIndexLength];
		
		int n = 0;
		for(int i = 0; i < sharedIndices.Length; i++)
		{
			if(!used.Contains(i))
				rebuild[n++] = sharedIndices[i];
		}

		sharedIndices = rebuild.Add( new pb_IntArray(newSharedIndex.ToArray()) );
		// SetSharedIndices( rebuild.Add( new pb_IntArray(newSharedIndex.ToArray()) ) );

		return sharedIndices.Length-1;
	}
Пример #21
0
	public static pb_IntArray[] ToPbIntArray(this List<List<int>> val)
	{
		pb_IntArray[] arr = new pb_IntArray[val.Count];
		for(int i = 0; i < arr.Length; i++)
			arr[i] = (pb_IntArray)val[i].ToArray();
		return arr;
	}
	/**
	 * Add a value to the array at index.
	 */
	public static int AddValueAtIndex(ref pb_IntArray[] sharedIndices, int sharedIndex, int value)
	{
		if(sharedIndex > -1)
			sharedIndices[sharedIndex].array = sharedIndices[sharedIndex].array.Add(value);
		else
			sharedIndices = (pb_IntArray[])sharedIndices.Add( new pb_IntArray(new int[]{value}) );
		
		return sharedIndex > -1 ? sharedIndex : sharedIndices.Length-1;
	}
Пример #23
0
	/**
	 *	\brief Cycles through a mesh and returns a pb_IntArray[] of 
	 *	triangles that point to the same point in world space.
	 *	@param _mesh The mesh to examine.
	 *	\sa pb_IntArray
	 *	\notes pbIntArray exists because Unity cannot serialize jagged arrays.
	 *	\returns A pb_IntArray[] (basically just an int[][] with some added functionality).
	 */
	public static pb_IntArray[] ExtractSharedIndices(Vector3[] v)
	{
		Dictionary<pb_IntVec3, List<int>> sorted = new Dictionary<pb_IntVec3, List<int>>();

		List<int> ind;

		for(int i = 0; i < v.Length; i++)
		{
			if( sorted.TryGetValue(v[i], out ind) )
				ind.Add(i);
			else
				sorted.Add(new pb_IntVec3(v[i]), new List<int>() { i });
		}

		pb_IntArray[] share = new pb_IntArray[sorted.Count];

		int t = 0;
		foreach(KeyValuePair<pb_IntVec3, List<int>> kvp in sorted)	
			share[t++] = new pb_IntArray( kvp.Value.ToArray() );

		return share;
	}
	/**
	 * Removes all passed values from the sharedIndices jagged array. Does NOT perform any
	 * index shifting to account for removed vertices.  Use RemoveValuesAndShift
	 * for that purpose.
	 */
	public static void RemoveValues(ref pb_IntArray[] sharedIndices, int[] remove)
	{
		// remove face indices from all shared indices caches
		for(int i = 0; i < sharedIndices.Length; i++)
		{
			for(int n = 0; n < remove.Length; n++)
			{
				int ind = System.Array.IndexOf(sharedIndices[i], remove[n]);

				if(ind > -1)
					sharedIndices[i].array = sharedIndices[i].array.RemoveAt(ind);
			}
		}

		// Remove empty or null entries caused by shifting around all them indices
		pb_IntArray.RemoveEmptyOrNull(ref sharedIndices);
	}
Пример #25
0
	/**
	 *	\brief Removes the specified indices from the array, and shifts all values 
	 *	down to account for removal in the vertex array.  Only use when deleting
	 *	faces or vertices.  For general moving around and modification of shared 
	 *	index array, use #RemoveValuesAtIndex.
	 */
	public static void RemoveValuesAndShift(ref pb_IntArray[] sharedIndices, IList<int> remove)
	{
		Dictionary<int, int> lookup = sharedIndices.ToDictionary();

		for(int i = 0; i < remove.Count; i++)
			lookup[remove[i]] = -1;

		sharedIndices = lookup.Where(x => x.Value > -1).ToSharedIndices();

		List<int> removed_values = new List<int>(remove);

		removed_values.Sort();
	
		for(int i = 0; i < sharedIndices.Length; i++)
		{
			for(int n = 0; n < sharedIndices[i].Length; n++)
			{
				int index = pbUtil.NearestIndexPriorToValue(removed_values, sharedIndices[i][n]);
				// add 1 because index is zero based
				sharedIndices[i][n] -= index+1;
			}
		}

	}
	// Copy constructor
	public pb_IntArray(pb_IntArray intArray)
	{
		array = intArray.array;
	}
Пример #27
0
	/**
	 * Creates a new pb_Object instance with the provided vertices, faces, and sharedIndex information.
	 */
	public static pb_Object CreateInstanceWithElements(Vector3[] v, Vector2[] u, Color[] c, pb_Face[] f, pb_IntArray[] si, pb_IntArray[] si_uv)
	{
		GameObject _gameObject = new GameObject();
		pb_Object pb = _gameObject.AddComponent<pb_Object>();

		pb.SetVertices(v);
		pb.SetUV(u);
		pb.SetColors(c);

		pb.SetSharedIndices( si ?? pb_IntArrayUtility.ExtractSharedIndices(v) );

		pb.SetSharedIndicesUV( si_uv ?? new pb_IntArray[0] {});

		pb.SetFaces(f);

		pb.ToMesh();
		pb.Refresh();

		pb.GetComponent<pb_Entity>().SetEntity(EntityType.Detail);

		return pb;
	}
Пример #28
0
	/**
	 *	\brief Averages shared normals with the mask of 'all' (indices contained in perimeter edge)
	 */
	private static Vector3 Norm( int tri, pb_IntArray[] shared, int[] all, Vector3[] norm )
	{
		int sind = shared.IndexOf(tri);
		
		if(sind < 0)
			return Vector3.zero;

		int[] triGroup = shared[sind];

		Vector3 n = Vector3.zero;
		int count = 0;
		for(int i = 0; i < all.Length; i++)
		{
			// this is a point in the perimeter, add it to the average
			if( System.Array.IndexOf(triGroup, all[i]) > -1 )
			{
				n += norm[all[i]];
				count++;
			}
		}
		return n / (float)count;
	}
Пример #29
0
	/**
	 * Creates a new pb_Object instance with the provided vertices, faces, and sharedIndex information.
	 */
	public static pb_Object CreateInstanceWithVerticesFacesSharedIndices(Vector3[] v, pb_Face[] f, pb_IntArray[] si)
	{
		GameObject _gameObject = new GameObject();
		pb_Object pb = _gameObject.AddComponent<pb_Object>();
		pb.GeometryWithVerticesFacesIndices(v, f, si);	
		pb.entity.SetEntity(EntityType.Detail);

		return pb;
	}