

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();
}
}