PPTGeneratorRender.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Threading;
  4. using PPTParticleSystem2D;
  5. //Generator for the PPT Particle System
  6. public class PPTGeneratorRender : MonoBehaviour
  7. {
  8. //Core of the PPT Particle System
  9. private PPTParticleSystem physics;
  10. //Texture to make as a particle system
  11. //Alpha Channel supported (each alpha = 0 means no particle)
  12. private Texture2D image;
  13. public RenderTexture tex;
  14. //Final ressolution for the particle system
  15. //Small value mean more resolution
  16. [Range(0.1f, 100)]
  17. public float resolution = 6;
  18. //A minium and maxim value for a random mass for the particles
  19. public float minimMassValue = 0.4f;
  20. public float maxMassValue = 0.8f;
  21. //Values for the spring and damping particles system
  22. public float springConstant=0.02f, damping=0.04f;
  23. //Particle Sistem from unity used to make the render of the particles
  24. public ParticleSystem ParticleSystem;
  25. //External forces applyied to the system
  26. public PPTForceParticle[] externalForces;
  27. //Use or not the localTransformPosition from the external forces
  28. public bool localPosition = false;
  29. //Particle method system to calculate the steps
  30. public PPTParticleSystem.IntegratorSystem integratorSystem;
  31. //Bolean flag to know if the particle system is loaded
  32. public bool isLoaded;
  33. //Value to make more viscosity effect
  34. [Range(0, 0.7f)]
  35. public float somedrag;
  36. //Enable or disable the srpings system
  37. public bool springsActivated = true;
  38. //the size of the representation of the system
  39. public float size = 1;
  40. //Internal variables for the map of the texture.
  41. private int widthSmall, heightSmall, numPixelsSmall;
  42. private PPTParticle[] particles;
  43. private PPTSpring[] springs;
  44. private PPTParticle[] fixedParticles;
  45. private Color[] colors;
  46. private float[] forceInstance;
  47. private bool[] activeInstance;
  48. private PPTParticle[] instances;
  49. private PPTAttraction[,] attracts;
  50. private UnityEngine.ParticleSystem.Particle[] parts;
  51. private bool m_springsActivated=true;
  52. //Multi thread for optimitzation
  53. private Thread thread;
  54. private Mutex mainLoop;
  55. void OnApplicationQuit()
  56. {
  57. //Kill the thread from the PPTParticleSystem
  58. thread.Abort();
  59. }
  60. void Start()
  61. {
  62. Camera.main.gameObject.AddComponent<CameraRender> ();
  63. Camera.main.gameObject.GetComponent<CameraRender> ().script = this;
  64. image=new Texture2D(tex.width, tex.height, TextureFormat.RGB24, false);
  65. RenderTexture.active = tex;
  66. image.ReadPixels(new Rect(0, 0, tex.width, tex.height), 0, 0);
  67. image.Apply();
  68. //Start the loading for the PPTParticleSystem
  69. LoadParticles();
  70. }
  71. // Use this for initialization
  72. public void LoadParticles()
  73. {
  74. isLoaded = false;
  75. //get the final ressolution for the system
  76. widthSmall = (int)(image.width / resolution);
  77. heightSmall = (int)(image.height / resolution);
  78. numPixelsSmall = 0;
  79. for (int x = 0; x < widthSmall; x++)
  80. {
  81. for (int y = 0; y < heightSmall; y++)
  82. {
  83. //Count each particle from the alpha cut off
  84. // Color c = image.GetPixel((int)(x * resolution), (int)(y * resolution));
  85. numPixelsSmall++;
  86. }
  87. }
  88. //Define an array for the colors of the image
  89. colors = new Color[numPixelsSmall];
  90. //Define a PPTParticle system
  91. physics = new PPTParticleSystem(0f, somedrag);
  92. //Define the integrator system
  93. physics.setIntegrator(integratorSystem);
  94. //Define one particle array system
  95. particles = new PPTParticle[numPixelsSmall];
  96. //Define another array of the particle system for the static position
  97. fixedParticles = new PPTParticle[numPixelsSmall];
  98. //Define each spring for each particle
  99. springs = new PPTSpring[numPixelsSmall];
  100. //Define each attract for the external force
  101. attracts = new PPTAttraction[externalForces.Length, numPixelsSmall];
  102. //Define each external force instance
  103. instances = new PPTParticle[externalForces.Length];
  104. forceInstance = new float[externalForces.Length];
  105. activeInstance = new bool[externalForces.Length];
  106. //For each external force, make a fixed particle
  107. Vector3 v = new Vector3(0, 0, 0);
  108. for (int i = 0; i < externalForces.Length; i++)
  109. {
  110. if (localPosition)
  111. v = externalForces[i].transform.localPosition;
  112. else
  113. v = externalForces[i].transform.position;
  114. //Make a fixed particle
  115. instances[i] = physics.makeParticle(1, v.x, v.y, v.z);
  116. instances[i].makeFixed();
  117. forceInstance[i] = externalForces[i].forceParticle;
  118. activeInstance[i] = externalForces[i].gameObject.activeSelf;
  119. }
  120. //Now we work with the particle's system
  121. int a = 0;
  122. for (int x = 0; x < widthSmall; x++)
  123. {
  124. for (int y = 0; y < heightSmall; y++)
  125. {
  126. //get the current color of the image
  127. Color c = image.GetPixel((int)(x * resolution), (int)(y * resolution));
  128. //get the current color
  129. colors[a] = image.GetPixel((int)(x * resolution), (int)(y * resolution));
  130. //make a particle
  131. particles[a] = physics.makeParticle(
  132. Random.Range(minimMassValue, maxMassValue),
  133. (x * resolution - widthSmall * resolution / 2)/(60/size),
  134. (y * resolution - heightSmall * resolution / 2)/(60/size), 0);
  135. //make a static particle
  136. fixedParticles[a] = physics.makeParticle(
  137. Random.Range(minimMassValue, maxMassValue),
  138. (x * resolution - widthSmall * resolution / 2)/(60/size),
  139. (y * resolution - heightSmall * resolution / 2)/(60/size), 0);
  140. //active the fixed particle for the static particle
  141. fixedParticles[a].makeFixed();
  142. int i = 0;
  143. //for each force...
  144. foreach (PPTParticle p in instances)
  145. {
  146. //apply the attracttion for each external force
  147. attracts[i, a] = physics.makeAttraction(particles[a], p, forceInstance[i], 0.1f);
  148. if (!activeInstance[i])
  149. //turn off the current attractot if the external force isn't enabled
  150. attracts[i, a].turnOff();
  151. i++;
  152. }
  153. //Finally make the spring joint between particle and fixed particle
  154. springs[a] = physics.makeSpring(particles[a], fixedParticles[a], springConstant, damping, 0);
  155. a++;
  156. }
  157. }
  158. //Particle system loaded
  159. isLoaded = true;
  160. //Internal array of particles to work with the Unityt particle system
  161. parts = new ParticleSystem.Particle[numPixelsSmall];
  162. mainLoop = new Mutex(true);
  163. thread = new Thread(runPhysics);
  164. //Atart a thread to make the particle system run
  165. thread.Start();
  166. //Getting the actual Unity particle system to make the new one
  167. if (ParticleSystem != null)
  168. {
  169. float particleSize = ParticleSystem.startSize;
  170. int i = numPixelsSmall;
  171. while (--i > -1)
  172. {
  173. ParticleSystem.Particle particle = new ParticleSystem.Particle();
  174. particle.position = new Vector2(particles[i].position.x,particles[i].position.y);
  175. particle.startLifetime = float.MaxValue;
  176. particle.remainingLifetime = float.MaxValue;
  177. particle.size = particleSize;
  178. particle.color = colors[i];
  179. parts[i] = particle;
  180. }
  181. ParticleSystem.SetParticles(parts, parts.Length);
  182. ParticleSystem.Play();
  183. }
  184. else {
  185. Debug.LogError("Particle system not setted! Please attach one Unity particle system to the PPTParticleSystem.");
  186. }
  187. }
  188. bool hold=false;
  189. public void OnPostRender() {
  190. hold=false;
  191. RenderTexture.active = tex;
  192. image.ReadPixels(new Rect(0, 0, tex.width, tex.height), 0, 0);
  193. image.Apply();
  194. hold = true;
  195. }
  196. void Update()
  197. {
  198. //For each force, update the state, force and position
  199. updateExternalForces();
  200. //Make the update of the particle system
  201. if (physics != null)
  202. updateParticleSystem();
  203. //Update the spring relations into the PPT Particle System
  204. updateSpringSystem();
  205. mainLoop.ReleaseMutex();
  206. mainLoop.WaitOne();
  207. }
  208. private void updateSpringSystem()
  209. {
  210. //Reload the spring state
  211. if (m_springsActivated != springsActivated)
  212. {
  213. m_springsActivated = springsActivated;
  214. foreach (PPTSpring s in springs)
  215. if (m_springsActivated)
  216. s.turnOn();
  217. else
  218. s.turnOff();
  219. }
  220. }
  221. //we work with the external forces that will reppel the particles
  222. private void updateExternalForces()
  223. {
  224. Vector3 v = new Vector3(0, 0, 0);
  225. for (int i = 0; i < externalForces.Length; i++)
  226. {
  227. if (localPosition)
  228. v = externalForces[i].transform.localPosition;
  229. else
  230. v = externalForces[i].transform.position;
  231. //Update position for each external force
  232. instances[i].position.x = v.x;
  233. instances[i].position.y = v.y;
  234. instances[i].position.z = v.z;
  235. if (forceInstance[i] != externalForces[i].forceParticle || activeInstance[i] != externalForces[i].gameObject.activeSelf)
  236. {
  237. forceInstance[i] = externalForces[i].forceParticle;
  238. activeInstance[i] = externalForces[i].gameObject.activeSelf;
  239. if (activeInstance[i])
  240. for (int a = 0; a < numPixelsSmall; a++)
  241. {
  242. //Turn on and setup the force for the external force
  243. attracts[i, a].turnOn();
  244. attracts[i, a].setStrength(forceInstance[i]);
  245. }
  246. else
  247. for (int a = 0; a < numPixelsSmall; a++)
  248. //Turn off the external force
  249. attracts[i, a].turnOff();
  250. }
  251. }
  252. }
  253. public void runPhysics()
  254. {
  255. while (true)
  256. {
  257. //Thread to run the core of the PPT Particle System
  258. Thread.Sleep(0);
  259. physics.tick();
  260. mainLoop.WaitOne();
  261. mainLoop.ReleaseMutex();
  262. }
  263. }
  264. public void updateParticleSystem()
  265. {
  266. //Get the current array of particles
  267. ParticleSystem.GetParticles(parts);
  268. //For each particle of Unity particle system, update the position and life
  269. int i = Mathf.Min(numPixelsSmall, particles.Length);
  270. int currentPixelX = widthSmall;
  271. int currentPixelY = heightSmall;
  272. //we update the color each frame in order to represent the texture
  273. while (--i > -1)
  274. {
  275. parts[i].position = new Vector2(particles[i].position.x, particles[i].position.y);
  276. parts[i].remainingLifetime = float.MaxValue;
  277. parts[i].color = image.GetPixel((int)(currentPixelX*resolution), (int)((currentPixelY)*resolution));
  278. if (currentPixelY > 1){
  279. if (currentPixelY == heightSmall){
  280. currentPixelX--;
  281. }
  282. currentPixelY--;
  283. }else{
  284. currentPixelY = heightSmall;
  285. parts[i].color = new Color(0,0,0,0);
  286. }
  287. }
  288. //Attach the new array to the current Unity particle system
  289. ParticleSystem.SetParticles(parts, particles.Length);
  290. }
  291. }