123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- using System.Collections;
- using System.Collections.Generic;
- using Unity.Collections;
- using Unity.Jobs;
- using UnityEngine;
- /// <summary>
- /// Used in the ZED planetarium sample to draw asteroids in the solar system's asteroid belt and rotate them.
- /// The asteroids are not instantiated as GameObjects, but drawn each frame with DrawMeshInstanced.
- /// Given there are many asteroids to draw, this reduces draw calls substantially along with some CPU overhead.
- /// </summary>
- public class AsteroidsManager : MonoBehaviour
- {
- /// <summary>
- /// Prefab containing the first asteroid mesh type.
- /// </summary>
- [Tooltip("Prefab containing the first asteroid mesh type.")]
- public GameObject asteroidsType1;
- /// <summary>
- /// Prefab containing the first asteroid mesh type.
- /// </summary>
- [Tooltip("Prefab containing the first asteroid mesh type.")]
- public GameObject asteroidsType2;
- /// <summary>
- /// How many asteroids of each type to draw. (There will be twice this number of asteroids in total).
- /// </summary>
- [Tooltip("How many asteroids of each type to draw. (There will be twice this number of asteroids in total).")]
- public static int amount = 100;
- /// <summary>
- /// The radius of the asteroid belt. This is meters when the localscale of this object is 1,1,1.
- /// </summary>
- [Tooltip("The radius of the asteroid belt. This is meters when the localscale of this object is 1,1,1. ")]
- public float radius = 1;
- /// <summary>
- /// How wide the asteroids can be spaced apart. Values too low or high may cause asteroids to intersect Mars or Jupiter.
- /// </summary>
- [Tooltip("How wide the asteroids can be spaced apart. Values too low or high may cause asteroids to intersect Mars or Jupiter. ")]
- public float offset = 0.05f;
- /// <summary>
- /// Holds the transform of where the asteroid started when it was created (for asteroid type 1).
- /// </summary>
- Matrix4x4[] listPositionsOrigin = new Matrix4x4[amount];
- /// <summary>
- /// Holds the current transforms of the type 1 asteroids, updated each frame based on the solar system's location and its orbit.
- /// </summary>
- Matrix4x4[] listPositions = new Matrix4x4[amount];
- /// <summary>
- /// Holds the transform of where the asteroid started when it was created (for asteroid type 1).
- /// </summary>
- Matrix4x4[] listPositionsOrigin2 = new Matrix4x4[amount];
- /// <summary>
- /// Holds the current transforms of the type 2 asteroids, updated each frame based on the solar system's location and its orbit.
- /// </summary>
- Matrix4x4[] listPositions2 = new Matrix4x4[amount];
- void Start()
- {
- CreateAsteroids(listPositionsOrigin, amount, radius, offset); //Create all type 1 asteroids.
- CreateAsteroids(listPositionsOrigin2, amount, radius, offset); //Create all type 2 asteroids.
- }
- /// <summary>
- /// Fills the first Matrix array with the origin positions and scales of randomly positioned asteroids.
- /// </summary>
- /// <param name="listPositionsOrigin">Array to be populated with matrixes of each asteroid's starting transform.</param>
- /// <param name="amount">How many asteroids to make.</param>
- /// <param name="radius">Radius of the asteroid belt/</param>
- /// <param name="offset">How far each asteroid can randomly deviate from the radius.</param>
- private void CreateAsteroids(Matrix4x4[] listPositionsOrigin, int amount, float radius, float offset)
- {
- for (int i = 0; i < amount; ++i)
- {
- // 1. translation: displace along circle with 'radius' in range [-offset, offset]
- float angle = (float)i / (float)amount * 360.0f;
- float displacement = (Random.Range(0, 30) % (int)(2 * offset * 100)) / 100.0f - offset;
- float x = Mathf.Sin(angle) * radius + displacement;
- displacement = (Random.Range(0, 30) % (int)(2 * offset * 100)) / 100.0f - offset;
- float y = displacement * 2.0f; // keep height of asteroid field smaller compared to width of x and z
- displacement = (Random.Range(0, 30) % (int)(2 * offset * 100)) / 100.0f - offset;
- float z = Mathf.Cos(angle) * radius + displacement;
- Vector3 position = new Vector3(x, y, z);
- //position = center.TransformPoint(position);
- //// 2. scale: Scale between 0.05 and 0.25f
- float scale = Random.Range(0.1f, 0.3f);
- //model = glm::scale(model, glm::vec3(scale));
- // 3. rotation: add random rotation around a (semi)randomly picked rotation axis vector
- float rotAngle = (Random.Range(0, 100000) % 360);
-
- //Matrix4x4 m = Matrix4x4.TRS(position, Quaternion.identity, new Vector3(scale, scale, scale));
- Matrix4x4 m = Matrix4x4.TRS(position, Quaternion.Euler(rotAngle, rotAngle, rotAngle), new Vector3(scale, scale, scale));
- listPositionsOrigin[i] = m;
- }
-
- }
- /// <summary>
- /// Called each frame to move, rotate and scale the asteroids based on this object's transform and their orbit.
- /// </summary>
- /// <param name="listPositionsOrigin">All asteroids' initial matrixes.</param>
- /// <param name="listPositions">All asteroids' current matrixes.</param>
- void UpdatePosition(Matrix4x4[] listPositionsOrigin, Matrix4x4[] listPositions)
- {
- for (int i = 0; i < listPositionsOrigin.Length; ++i)
- {
- listPositionsOrigin[i] = listPositionsOrigin[i] * Matrix4x4.TRS(Vector3.zero,
- Quaternion.Euler(Time.deltaTime * Random.Range(0, 100), Time.deltaTime * Random.Range(0, 100), Time.deltaTime * Random.Range(0, 100)),
- Vector3.one);
- listPositions[i] = transform.localToWorldMatrix* ( listPositionsOrigin[i]);
- }
- }
- // Update is called once per frame
- void Update()
- {
- foreach(ZEDManager manager in ZEDManager.GetInstances())
- {
- DrawAsteroids(manager);
- }
-
- }
- private void DrawAsteroids(ZEDManager manager)
- {
- Camera leftcamera = manager.GetLeftCamera();
- Camera rightcamera = manager.GetRightCamera();
- //Update positions and draw asteroids of type 1
- UpdatePosition(listPositionsOrigin, listPositions);
- Graphics.DrawMeshInstanced(asteroidsType1.GetComponent<MeshFilter>().sharedMesh,
- 0, asteroidsType1.GetComponent<MeshRenderer>().sharedMaterial,
- listPositions,
- listPositions.Length,
- null,
- UnityEngine.Rendering.ShadowCastingMode.Off,
- false,
- gameObject.layer,
- leftcamera);
- if (manager.IsStereoRig)
- {
- Graphics.DrawMeshInstanced(asteroidsType1.GetComponent<MeshFilter>().sharedMesh,
- 0,
- asteroidsType1.GetComponent<MeshRenderer>().sharedMaterial,
- listPositions,
- listPositions.Length,
- null,
- UnityEngine.Rendering.ShadowCastingMode.Off,
- false,
- gameObject.layer,
- rightcamera);
- }
- //Update positions and draw asteroids of type 2
- UpdatePosition(listPositionsOrigin2, listPositions2);
- Graphics.DrawMeshInstanced(asteroidsType2.GetComponent<MeshFilter>().sharedMesh,
- 0,
- asteroidsType2.GetComponent<MeshRenderer>().sharedMaterial,
- listPositions2,
- listPositions2.Length,
- null,
- UnityEngine.Rendering.ShadowCastingMode.Off,
- false,
- gameObject.layer,
- leftcamera);
- if (manager.IsStereoRig)
- {
- Graphics.DrawMeshInstanced(asteroidsType2.GetComponent<MeshFilter>().sharedMesh,
- 0,
- asteroidsType2.GetComponent<MeshRenderer>().sharedMaterial,
- listPositions2,
- listPositions2.Length,
- null,
- UnityEngine.Rendering.ShadowCastingMode.Off,
- false,
- gameObject.layer,
- rightcamera);
- }
- }
- }
|