using UnityEngine; using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; using UnityEngine.UI; public class Argos_Particle_Spawner : MonoBehaviour { struct Particle { public Vector3 position; public Vector3 velocity; } public bool bCompute_Running = false; public Transform Source_Transform; public UI_Ladder ui_Ladder; public int Attractor_Mode; //0 - Pendulum : 1 - Frisbee private int attractor_Count; private GameObject[] go_Atts = new GameObject[20]; private float[] att_0 = new float[3]; private float[] att_1 = new float[3]; private float[] att_2 = new float[3]; private float[] att_3 = new float[3]; private float[] att_4 = new float[3]; private float[] att_5 = new float[3]; private float[] att_6 = new float[3]; private float[] att_7 = new float[3]; private float[] att_8 = new float[3]; private float[] att_9 = new float[3]; private float[] att_10 = new float[3]; private float[] att_11 = new float[3]; private float[] att_12 = new float[3]; private float[] att_13 = new float[3]; private float[] att_14 = new float[3]; private float[] att_15 = new float[3]; private float[] att_16 = new float[3]; private float[] att_17 = new float[3]; private float[] att_18 = new float[3]; private float[] att_19 = new float[3]; public Double_Slider color_double_slider; public Velocity_Color_Slider velocity_color_slider; public bool bPrimary; public UI_Control ui_control; public ShowHide_UI showHide_UI; public HMD_Ctrl_Tracking hmd_Ctrl_Tracking; public Text BlendMode_Txt; public Slider speedSwitch_Slider; float speedSwitch_Value; public Text speedSwitch_Text; public Slider constVel_Slider; float constVel_Value; public Text constVel_Text; public Slider geomScale_Slider; float geomScale_Value; public Text geomScale_Text; public ComputeShader computeShader; public Material material; public int maxParticles = 32; public GameObject pendulum_Handle; //Handle public GameObject orbitingSphere; public GameObject Frisbee; public GameObject Frisbee_Attractor_Right; public GameObject Frisbee_Attractor_Left; public Color_Swatches color_Swatches; public float targetStrength = 1000;//POWER MAG public float particle_size = 1f; public float timeMod = 1f; public float damping = 0f; public float orbit_weighting = 0.5f; public float radius_of_action = 1.0f; public float roa_amplitude = 0; public float roa_frequency = 0; public float constVel = 0; public float cubeSize = 100; public float maxAge = 3.0f; public float particleSize = 0.5f; private ComputeBuffer particles; private int particleSizeOf; private ComputeBuffer writeFromCompute; private int writeSizeOf; int kernel; public static List<Argos_Particle_Spawner> aps_list;// Static list, just to call Render() from the camera. void Start() { if (aps_list == null) aps_list = new List<Argos_Particle_Spawner>(); aps_list.Add(this); StartCoroutine(Defer_LoadAttractors()); attractor_Count = 0; } IEnumerator Defer_LoadAttractors() { yield return new WaitForSeconds(0.01f); hmd_Ctrl_Tracking.setAttractors(ref go_Atts, ref attractor_Count); bCompute_Running = true; } public void Set_Attractor_Mode(int mode) { Attractor_Mode = mode; } public void initParicleBuffer_Parbolic() { kernel = computeShader.FindKernel("CSMain"); if (particles != null) particles.Dispose(); particles = null; Particle p = new Particle(); particleSizeOf = Marshal.SizeOf(p); Particle[] pInitBuffer = new Particle[maxParticles]; int num = maxParticles; float fSeam = 0.5f; float offset = 1.0f / num; float increment = Mathf.PI * (3 - Mathf.Sqrt(5.0f)); int idx = 0; Vector3 v; Vector3 pAdj; for (int i = 0; i < num; i++) { float y = (i * offset); float r = Mathf.Sqrt(y); float phi = ((i + fSeam) % num) * increment; float x = Mathf.Cos(phi) * r; float z = Mathf.Sin(phi) * r; v = new Vector3(x, y-0.5f, z); v *= geomScale_Value / 3f; //ADD ADJUSTMENT TRANSFORM; pAdj = v.x * Source_Transform.right + v.y * Source_Transform.up + v.z * Source_Transform.forward + Source_Transform.position; p.position = pAdj; p.velocity = Vector3.zero; pInitBuffer[idx] = p; idx++; } particles = new ComputeBuffer(maxParticles, particleSizeOf, ComputeBufferType.Default); particles.SetData(pInitBuffer); computeShader.SetBuffer(kernel, "particles", particles); } public void initParicleBuffer_Fibonacci() { kernel = computeShader.FindKernel("CSMain"); if (particles != null) particles.Dispose(); particles = null; Particle p = new Particle(); particleSizeOf = Marshal.SizeOf(p); Particle[] pInitBuffer = new Particle[maxParticles]; int num = maxParticles; float fSeam = 0.5f; float offset = 2.0f / num; float increment = Mathf.PI * (3 - Mathf.Sqrt(5.0f)); int idx = 0; Vector3 v; Vector3 pAdj; for (int i = 0; i < num; i++) { float y = (i * offset) - 1 + (offset / 2.0f); float r = Mathf.Sqrt(1 - Mathf.Pow(y, 2)); float phi = ((i + fSeam) % num) * increment; float x = Mathf.Cos(phi) * r; float z = Mathf.Sin(phi) * r; v = new Vector3(x, y, z); v *= geomScale_Value/3f; //ADD ADJUSTMENT TRANSFORM; pAdj = v.x * Source_Transform.right + v.y * Source_Transform.up + v.z * Source_Transform.forward + Source_Transform.position; p.position = pAdj; p.velocity = Vector3.zero; pInitBuffer[idx] = p; idx++; } particles = new ComputeBuffer(maxParticles, particleSizeOf, ComputeBufferType.Default); particles.SetData(pInitBuffer); computeShader.SetBuffer(kernel, "particles", particles); } void initParicleBuffer_Laminar() { kernel = computeShader.FindKernel("CSMain"); if (particles != null) particles.Dispose(); particles = null; Particle p = new Particle(); particleSizeOf = Marshal.SizeOf(p); Particle[] pInitBuffer = new Particle[maxParticles]; float sideCount = Mathf.Floor(Mathf.Sqrt(((float)maxParticles)/4f)); float edgeDist = 1f / sideCount; float startX, startY, startZ; float rideX, rideY, rideZ; startX = startZ = rideX = rideZ = (int)((-sideCount / 2.0f) * edgeDist); startY = rideY = -2* edgeDist; int nSideCount = (int)sideCount; int idx = 0; Vector3 v; Vector3 pAdj; for (int i = 0; i < nSideCount; i++) { for (int j = 0; j < 4; j++) { for (int k = 0; k < nSideCount; k++) { p = new Particle(); v.x = rideX; v.y = rideY; v.z = rideZ; v *= geomScale_Value; pAdj = v.x * Source_Transform.right + v.y * Source_Transform.up + v.z * Source_Transform.forward + Source_Transform.position; p.position = pAdj; p.velocity = Vector3.zero; pInitBuffer[idx] = p; rideX += edgeDist; idx++; } rideX = startX; rideY += edgeDist; } rideX = startX; rideY = startY; rideZ += edgeDist; } particles = new ComputeBuffer(maxParticles, particleSizeOf, ComputeBufferType.Default); particles.SetData(pInitBuffer); computeShader.SetBuffer(kernel, "particles", particles); } void initParicleBuffer_Cube() { kernel = computeShader.FindKernel("CSMain"); if (particles != null) particles.Dispose(); particles = null; Particle p = new Particle(); particleSizeOf = Marshal.SizeOf(p); Particle[] pInitBuffer = new Particle[maxParticles]; float sideCount = Mathf.Floor(Mathf.Pow((float)maxParticles, 1.0f / 3.0f)); float edgeDist = 1f / sideCount; float startX, startY, startZ; float rideX, rideY, rideZ; startX = startZ = rideX = rideZ = (int)((-sideCount / 2.0f) * edgeDist); startY = rideY = (int)((-sideCount / 2.0f) * edgeDist); int nSideCount = (int)sideCount; int idx = 0; Vector3 v; Vector3 pAdj; for (int i = 0; i < nSideCount; i++) { for (int j = 0; j < nSideCount; j++) { for (int k = 0; k < nSideCount; k++) { p = new Particle(); //p.index = i; //p.type = 0; //p.age = 0; //p.normAge = 0.1f; //p.size = particleSize * 0.5f + particleSize; //if (bPrimary)//Hack //{ v.x = rideX; v.y = rideY; v.z = rideZ; v *= geomScale_Value; //v += vert_Offset; pAdj = v.x * Source_Transform.right + v.y * Source_Transform.up + v.z * Source_Transform.forward + Source_Transform.position; p.position = pAdj; p.velocity = Vector3.zero; pInitBuffer[idx] = p; rideX += edgeDist; idx++; } rideX = startX; rideY += edgeDist; } rideX = startX; rideY = startY; rideZ += edgeDist; } particles = new ComputeBuffer(maxParticles, particleSizeOf, ComputeBufferType.Default); particles.SetData(pInitBuffer); computeShader.SetBuffer(kernel, "particles", particles); } public void ResetCube() { initParicleBuffer_Cube(); } public void ResetFibonacci() { initParicleBuffer_Fibonacci(); } public void ResetLaminarFlow() { initParicleBuffer_Laminar(); } public void ResetParabolic() { initParicleBuffer_Parbolic(); } public void onZeroVelocity() { constVel_Slider.value = 0; } public void onSpeedSwitchSlider() { if (bPrimary) { speedSwitch_Value = speedSwitch_Slider.value*2000f; speedSwitch_Text.text = speedSwitch_Value.ToString("F2"); UI_Ladder.Instance.fine_Tuner.Active_FTS(speedSwitch_Slider); } } public void onConstVelSlider() { if (bPrimary) { constVel_Value = constVel_Slider.value; constVel_Text.text = constVel_Slider.value.ToString("F2"); UI_Ladder.Instance.fine_Tuner.Active_FTS(constVel_Slider); } } public void onGeomScaleSlider() { if (bPrimary) { geomScale_Value = geomScale_Slider.value; geomScale_Text.text = geomScale_Value.ToString("F2"); UI_Ladder.Instance.fine_Tuner.Active_FTS(geomScale_Slider); } } public void returnMasses_ToSpawn() { pendulum_Handle.GetComponent<Return_to_Spawn>().ResetToSpawn(); orbitingSphere.GetComponent<Return_to_Spawn>().ResetToSpawn(); Frisbee.GetComponent<Return_to_Spawn>().ResetToSpawn(); } public void SetAttractorCount(int cnt) { attractor_Count = cnt; } private void attractor_Frame_Gather() { att_0[0] = go_Atts[0].transform.position.x; att_0[1] = go_Atts[0].transform.position.y; att_0[2] = go_Atts[0].transform.position.z; att_1[0] = go_Atts[1].transform.position.x; att_1[1] = go_Atts[1].transform.position.y; att_1[2] = go_Atts[1].transform.position.z; att_2[0] = go_Atts[2].transform.position.x; att_2[1] = go_Atts[2].transform.position.y; att_2[2] = go_Atts[2].transform.position.z; att_3[0] = go_Atts[3].transform.position.x; att_3[1] = go_Atts[3].transform.position.y; att_3[2] = go_Atts[3].transform.position.z; att_4[0] = go_Atts[4].transform.position.x; att_4[1] = go_Atts[4].transform.position.y; att_4[2] = go_Atts[4].transform.position.z; att_5[0] = go_Atts[5].transform.position.x; att_5[1] = go_Atts[5].transform.position.y; att_5[2] = go_Atts[5].transform.position.z; att_6[0] = go_Atts[6].transform.position.x; att_6[1] = go_Atts[6].transform.position.y; att_6[2] = go_Atts[6].transform.position.z; att_7[0] = go_Atts[7].transform.position.x; att_7[1] = go_Atts[7].transform.position.y; att_7[2] = go_Atts[7].transform.position.z; att_8[0] = go_Atts[8].transform.position.x; att_8[1] = go_Atts[8].transform.position.y; att_8[2] = go_Atts[8].transform.position.z; att_9[0] = go_Atts[9].transform.position.x; att_9[1] = go_Atts[9].transform.position.y; att_9[2] = go_Atts[9].transform.position.z; att_10[0] = go_Atts[10].transform.position.x; att_10[1] = go_Atts[10].transform.position.y; att_10[2] = go_Atts[10].transform.position.z; att_11[0] = go_Atts[11].transform.position.x; att_11[1] = go_Atts[11].transform.position.y; att_11[2] = go_Atts[11].transform.position.z; att_12[0] = go_Atts[12].transform.position.x; att_12[1] = go_Atts[12].transform.position.y; att_12[2] = go_Atts[12].transform.position.z; att_13[0] = go_Atts[13].transform.position.x; att_13[1] = go_Atts[13].transform.position.y; att_13[2] = go_Atts[13].transform.position.z; att_14[0] = go_Atts[14].transform.position.x; att_14[1] = go_Atts[14].transform.position.y; att_14[2] = go_Atts[14].transform.position.z; att_15[0] = go_Atts[15].transform.position.x; att_15[1] = go_Atts[15].transform.position.y; att_15[2] = go_Atts[15].transform.position.z; att_16[0] = go_Atts[16].transform.position.x; att_16[1] = go_Atts[16].transform.position.y; att_16[2] = go_Atts[16].transform.position.z; att_17[0] = go_Atts[17].transform.position.x; att_17[1] = go_Atts[17].transform.position.y; att_17[2] = go_Atts[17].transform.position.z; att_18[0] = go_Atts[18].transform.position.x; att_18[1] = go_Atts[18].transform.position.y; att_18[2] = go_Atts[18].transform.position.z; att_19[0] = go_Atts[19].transform.position.x; att_19[1] = go_Atts[19].transform.position.y; att_19[2] = go_Atts[19].transform.position.z; } void FixedUpdate() { if (bCompute_Running) { if (go_Atts[0] != null) { attractor_Frame_Gather(); } computeShader.SetFloat("time", Time.time); float[] targ1 = { 0f, 0f, 0f }; float[] targ2 = { 0f, 0f, 0f }; Vector3 pos; if (Attractor_Mode == 0) { pos = pendulum_Handle.transform.position; } else { pos = Frisbee_Attractor_Left.transform.position; } targ1[0] = pos.x; targ1[1] = pos.y; targ1[2] = pos.z; if (Attractor_Mode == 0) { pos = orbitingSphere.transform.position; } else { pos = Frisbee_Attractor_Right.transform.position; } targ2[0] = pos.x; targ2[1] = pos.y; targ2[2] = pos.z; orbit_weighting = 0.5f; targetStrength = ui_Ladder.pParticlePower; orbit_weighting = ui_control.orbit_weighting; particleSize = ui_Ladder.particleSize; radius_of_action = ui_control.Radius_of_Action; roa_amplitude = ui_control.ROA_Amplitude; roa_frequency = ui_control.ROA_Frequency; modulate_ROA(); if (ui_Ladder.bStop_Time_Tog_On) { timeMod = 0; } else { timeMod = ui_Ladder.timeMod_Val * 1f / 90f; } damping = 1 - 0.05f * ui_Ladder.damping_Val; // Initialise the compute shader variables. computeShader.SetFloat("targetStrengh", targetStrength); computeShader.SetFloat("deltaTime", timeMod); computeShader.SetFloat("damping", damping); computeShader.SetFloats("base", targ1); computeShader.SetFloats("orbit", targ2); computeShader.SetFloat("orbit_weighting", orbit_weighting); computeShader.SetFloat("radius_of_action", radius_of_action); computeShader.SetFloat("constVel", constVel_Value*3000f); computeShader.SetFloats("att_0", att_0); computeShader.SetFloats("att_1", att_1); computeShader.SetFloats("att_2", att_2); computeShader.SetFloats("att_3", att_3); computeShader.SetFloats("att_4", att_4); computeShader.SetFloats("att_5", att_5); computeShader.SetFloats("att_6", att_6); computeShader.SetFloats("att_7", att_7); computeShader.SetFloats("att_8", att_8); computeShader.SetFloats("att_9", att_9); computeShader.SetFloats("att_10", att_10); computeShader.SetFloats("att_11", att_11); computeShader.SetFloats("att_12", att_12); computeShader.SetFloats("att_13", att_13); computeShader.SetFloats("att_14", att_14); computeShader.SetFloats("att_15", att_15); computeShader.SetFloats("att_16", att_16); computeShader.SetFloats("att_17", att_17); computeShader.SetFloats("att_18", att_18); computeShader.SetFloats("att_19", att_19); computeShader.SetInt("attractor_Count", attractor_Count); uint x, y, z; computeShader.GetKernelThreadGroupSizes(kernel, out x, out y, out z); computeShader.Dispatch(kernel, maxParticles, 1, 1); } } void modulate_ROA() { float unit = radius_of_action; float amp = unit * roa_amplitude; radius_of_action = unit + amp * Mathf.Sin(roa_frequency * Time.time * 2 * Mathf.PI); } // Called by the PendulumRender in OnRender public void Render() { if (bPrimary) { material.SetPass(0); material.SetVector("_worldpos", transform.position); material.SetBuffer("particles", particles); material.SetFloat("_particleSize", particleSize); material.SetColor("_LowColor", color_Swatches.Low_Color); material.SetColor("_MidColor", color_Swatches.Mid_Color); material.SetColor("_HighColor", color_Swatches.High_Color); material.SetFloat("_colorSwitch", speedSwitch_Value); material.SetFloat("_LowMidThresh", velocity_color_slider.getLowMid_Threshold()); material.SetFloat("_HighMidThresh", velocity_color_slider.getMidHigh_Threshold()); material.SetFloat("_nPerc", ui_Ladder.pctBandColorLrp); int blendMode = ui_Ladder.getBlendMode(); //BlendMode_Txt.text = blendMode.ToString(); if (blendMode == 0) { material.SetInt("_ARG_SrcMode", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); material.SetInt("_ARG_DstMode", (int)UnityEngine.Rendering.BlendMode.Zero); } else if (blendMode == 1) { material.SetInt("_ARG_SrcMode", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); material.SetInt("_ARG_DstMode", (int)UnityEngine.Rendering.BlendMode.One); } else { material.SetInt("_ARG_SrcMode", (int)UnityEngine.Rendering.BlendMode.SrcColor); material.SetInt("_ARG_DstMode", (int)UnityEngine.Rendering.BlendMode.DstColor); } Graphics.DrawProcedural(MeshTopology.Points, maxParticles, 0); } } void OnDisable() { particles.Release(); } }