123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- using UnityEngine;
- using System.Collections;
- using ProBuilder2.Common;
-
- /**
- * Move a sphere around the surface of a ProBuilder mesh, changing the
- * vertex color of the nearest face.
- *
- * Scene setup: Create a Unity Sphere primitive in a new scene, then attach
- * this script to the sphere. Press 'Play'
- */
- public class HighlightNearestFace : MonoBehaviour
- {
- // The distance covered by the plane.
- public float travel = 50f;
- // The speed at which the sphere will move.
- public float speed = .2f;
- // ProBuilder mesh component
- private pb_Object target;
- // The nearest face to this sphere.
- private pb_Face nearest = null;
-
- void Start()
- {
- // Generate a 50x50 plane with 25 subdivisions, facing up, with no smoothing applied.
- target = pb_ShapeGenerator.PlaneGenerator(travel, travel, 25, 25, ProBuilder2.Common.Axis.Up, false);
-
- target.SetFaceMaterial(target.faces, pb_Constant.DefaultMaterial);
-
- target.transform.position = new Vector3(travel * .5f, 0f, travel * .5f);
-
- // Rebuild the mesh (apply pb_Object data to UnityEngine.Mesh)
- target.ToMesh();
-
- // Rebuild UVs, Colors, Collisions, Normals, and Tangents
- target.Refresh();
-
- // Orient the camera in a good position
- Camera cam = Camera.main;
- cam.transform.position = new Vector3(25f, 40f, 0f);
- cam.transform.localRotation = Quaternion.Euler( new Vector3(65f, 0f, 0f) );
- }
-
- void Update()
- {
- float time = Time.time * speed;
-
- Vector3 position = new Vector3(
- Mathf.PerlinNoise(time, time) * travel,
- 2,
- Mathf.PerlinNoise(time + 1f, time + 1f) * travel
- );
-
- transform.position = position;
-
- if(target == null)
- {
- Debug.LogWarning("Missing the ProBuilder Mesh target!");
- return;
- }
-
- // instead of testing distance by converting each face's center to world space,
- // convert the world space of this object to the pb-Object local transform.
- Vector3 pbRelativePosition = target.transform.InverseTransformPoint(transform.position);
-
- // reset the last colored face to white
- if(nearest != null)
- target.SetFaceColor(nearest, Color.white);
-
- // iterate each face in the pb_Object looking for the one nearest
- // to this object.
- int faceCount = target.faces.Length;
- float smallestDistance = Mathf.Infinity;
- nearest = target.faces[0];
-
- for(int i = 0; i < faceCount; i++)
- {
- float distance = Vector3.Distance(pbRelativePosition, FaceCenter(target, target.faces[i]));
-
- if(distance < smallestDistance)
- {
- smallestDistance = distance;
- nearest = target.faces[i];
- }
- }
-
- // Set a single face's vertex colors. If you're updating more than one face, consider using
- // the pb_Object.SetColors(Color[] colors); function instead.
- target.SetFaceColor(nearest, Color.blue);
-
- // Apply the stored vertex color array to the Unity mesh.
- target.RefreshColors();
- }
-
- /**
- * Returns the average of each vertex position in a face.
- * In local space.
- */
- private Vector3 FaceCenter(pb_Object pb, pb_Face face)
- {
- Vector3[] vertices = pb.vertices;
-
- Vector3 average = Vector3.zero;
-
- // face holds triangle data. distinctIndices is a
- // cached collection of the distinct indices that
- // make up the triangles. Ex:
- // tris = {0, 1, 2, 2, 3, 0}
- // distinct indices = {0, 1, 2, 3}
- foreach(int index in face.distinctIndices)
- {
- average.x += vertices[index].x;
- average.y += vertices[index].y;
- average.z += vertices[index].z;
- }
-
- float len = (float) face.distinctIndices.Length;
-
- average.x /= len;
- average.y /= len;
- average.z /= len;
-
- return average;
- }
- }
|