color picker
application button
second pendulum
using UnityEngine; using System.Collections; using VRTK; using UnityEngine.UI; // Author: Eric Eastwood (ericeastwood.com) // // Description: // Written for this gd.se question: http://gamedev.stackexchange.com/a/75748/16587 // Simulates/Emulates pendulum motion in code // Works in any 3D direction and with any force/direciton of gravity // // Demonstration: https://i.imgur.com/vOQgFMe.gif // // Usage: https://i.imgur.com/BM52dbT.png public class Pendulum : MonoBehaviour { public GameObject Pivot; public GameObject Bob; public VRTK_ControllerEvents ctrl_events; private Vector2 vTouchAxis = Vector2.zero; public Text debugText; public float mass = 1f; float bob_length = 500f; public float dampFactor = 1f; Vector3 bobStartingPosition; bool bobStartingPositionSet = false; // You could define these in the `PendulumUpdate()` loop // But we want them in the class scope so we can draw gizmos `OnDrawGizmos()` public Vector3 vGravity; public UI_Control uiControl; private Vector3 gravityDirection; private Vector3 tensionDirection; private Vector3 tangentDirection; private Vector3 pendulumSideDirection; private float tensionForce = 0f; private float gravityForce = 0f; // Keep track of the current velocity Vector3 currentVelocity = new Vector3(); // We use these to smooth between values in certain framerate situations in the `Update()` loop Vector3 currentStatePosition; Vector3 previousStatePosition; // Use this for initialization void Start() { // Set the starting position for later use in the context menu reset methods this.bobStartingPosition = this.Bob.transform.position; this.bobStartingPositionSet = true; this.PendulumInit(); ctrl_events.TouchpadAxisChanged += new ControllerInteractionEventHandler(DoTouchpadAxisChanged); ctrl_events.TouchpadTouchEnd += new ControllerInteractionEventHandler(DoTouchpadTouchEnd); } private void DoTouchpadAxisChanged(object sender, ControllerInteractionEventArgs e) { SetTouchAxis(e.touchpadAxis, e.buttonPressure); } private void DoTouchpadTouchEnd(object sender, ControllerInteractionEventArgs e) { SetTouchAxis(Vector2.zero, e.buttonPressure); } private void SetTouchAxis(Vector2 touchpadAxis, float pressure) { vTouchAxis = touchpadAxis; float presf = pressure; debugText.text = "Touch = " + vTouchAxis.ToString("F3") + presf.ToString("F3"); } private void updateBobLength() { float delt = Time.deltaTime; bob_length += vTouchAxis.y * 10.0f * delt; } float t = 0f; float dt = 0.01f; float currentTime = 0f; float accumulator = 0f; void Update() { vGravity.y = -uiControl.pendulumGravity; //bob_length = uiControl.bob_length; updateBobLength(); /* */ // Fixed deltaTime rendering at any speed with smoothing // Technique: http://gafferongames.com/game-physics/fix-your-timestep/ float frameTime = Time.time - currentTime; this.currentTime = Time.time; this.accumulator += frameTime; while (this.accumulator >= this.dt) { this.previousStatePosition = this.currentStatePosition; this.currentStatePosition = this.PendulumUpdate(this.currentStatePosition, this.dt); //integrate(state, this.t, this.dt); accumulator -= this.dt; this.t += this.dt; } float alpha = this.accumulator / this.dt; Vector3 newPosition = this.currentStatePosition * alpha + this.previousStatePosition * (1f - alpha); this.Bob.transform.position = newPosition; //this.currentStatePosition; /* */ //this.Bob.transform.position = this.PendulumUpdate(this.Bob.transform.position, Time.deltaTime); } // Use this to reset forces and go back to the starting position [ContextMenu("Reset Pendulum Position")] public void ResetPendulumPosition() { ResetPendulumForces(); //if (this.bobStartingPositionSet) // this.MoveBob(this.bobStartingPosition); //else this.PendulumInit(); } // Use this to reset any built up forces [ContextMenu("Reset Pendulum Forces")] void ResetPendulumForces() { this.currentVelocity = Vector3.zero; // Set the transition state this.currentStatePosition = this.Bob.transform.position; } void PendulumInit() { // Get the initial rope length from how far away the bob is now this.bob_length = Vector3.Distance(Pivot.transform.position, Bob.transform.position); this.ResetPendulumForces(); } void MoveBob(Vector3 resetBobPosition) { // Put the bob back in the place we first saw it at in `Start()` this.Bob.transform.position = resetBobPosition; // Set the transition state this.currentStatePosition = resetBobPosition; } Vector3 PendulumUpdate(Vector3 currentStatePosition, float deltaTime) { // Add gravity free fall this.gravityForce = this.mass * vGravity.magnitude; this.gravityDirection = vGravity.normalized; this.currentVelocity += this.gravityDirection * this.gravityForce * deltaTime; Vector3 pivot_p = this.Pivot.transform.position; Vector3 bob_p = this.currentStatePosition; Vector3 auxiliaryMovementDelta = this.currentVelocity * deltaTime; float distanceAfterGravity = Vector3.Distance(pivot_p, bob_p + auxiliaryMovementDelta); // If at the end of the rope if (distanceAfterGravity > this.bob_length || Mathf.Approximately(distanceAfterGravity, this.bob_length)) { this.tensionDirection = (pivot_p - bob_p).normalized; this.pendulumSideDirection = (Quaternion.Euler(0f, 90f, 0f) * this.tensionDirection); this.pendulumSideDirection.Scale(new Vector3(1f, 0f, 1f)); this.pendulumSideDirection.Normalize(); this.tangentDirection = (-1f * Vector3.Cross(this.tensionDirection, this.pendulumSideDirection)).normalized; float inclinationAngle = Vector3.Angle(bob_p - pivot_p, this.gravityDirection); this.tensionForce = this.mass * Physics.gravity.magnitude * Mathf.Cos(Mathf.Deg2Rad * inclinationAngle); float centripetalForce = ((this.mass * Mathf.Pow(this.currentVelocity.magnitude, 2)) / this.bob_length); this.tensionForce += centripetalForce; this.currentVelocity += this.tensionDirection * this.tensionForce * deltaTime; this.currentVelocity = (1f - dampFactor/1000f) * this.currentVelocity; } // Get the movement delta Vector3 movementDelta = Vector3.zero; movementDelta += this.currentVelocity * deltaTime; //return currentStatePosition + movementDelta; float distance = Vector3.Distance(pivot_p, currentStatePosition + movementDelta); return this.GetPointOnLine(pivot_p, currentStatePosition + movementDelta, distance <= this.bob_length ? distance : this.bob_length); } Vector3 GetPointOnLine(Vector3 start, Vector3 end, float distanceFromStart) { return start + (distanceFromStart * Vector3.Normalize(end - start)); } void OnDrawGizmos() { // purple Gizmos.color = new Color(.5f, 0f, .5f); Gizmos.DrawWireSphere(this.Pivot.transform.position, this.bob_length); Gizmos.DrawWireCube(this.bobStartingPosition, new Vector3(.5f, .5f, .5f)); // Blue: Auxilary Gizmos.color = new Color(.3f, .3f, 1f); // blue Vector3 auxVel = .3f * this.currentVelocity; Gizmos.DrawRay(this.Bob.transform.position, auxVel); Gizmos.DrawSphere(this.Bob.transform.position + auxVel, .2f); // Yellow: Gravity Gizmos.color = new Color(1f, 1f, .2f); Vector3 gravity = .3f * this.gravityForce * this.gravityDirection; Gizmos.DrawRay(this.Bob.transform.position, gravity); Gizmos.DrawSphere(this.Bob.transform.position + gravity, .2f); // Orange: Tension Gizmos.color = new Color(1f, .5f, .2f); // Orange Vector3 tension = .3f * this.tensionForce * this.tensionDirection; Gizmos.DrawRay(this.Bob.transform.position, tension); Gizmos.DrawSphere(this.Bob.transform.position + tension, .2f); // Red: Resultant Gizmos.color = new Color(1f, .3f, .3f); // red Vector3 resultant = gravity + tension; Gizmos.DrawRay(this.Bob.transform.position, resultant); Gizmos.DrawSphere(this.Bob.transform.position + resultant, .2f); /* * / // Green: Pendulum side direction Gizmos.color = new Color(.3f, 1f, .3f); Gizmos.DrawRay(this.Bob.transform.position, 3f*this.pendulumSideDirection); Gizmos.DrawSphere(this.Bob.transform.position + 3f*this.pendulumSideDirection, .2f); /* */ /* * / // Cyan: tangent direction Gizmos.color = new Color(.2f, 1f, 1f); // cyan Gizmos.DrawRay(this.Bob.transform.position, 3f*this.tangentDirection); Gizmos.DrawSphere(this.Bob.transform.position + 3f*this.tangentDirection, .2f); /* */ } }
Shader "Argos_Compute/Tetra_Emitter" { Properties { _ParticleTexture("Diffuse Tex", 2D) = "white" {} _Color("Main Color", Color) = (0, 1, 1,0.3) _SpeedColor("Speed Color", Color) = (1, 0, 0, 0.3) _colorSwitch("Switch", Range(0, 120)) = 60 } SubShader { Pass { //Blend SrcAlpha OneMinusSrcAlpha // Traditional transparency //Blend One OneMinusSrcAlpha // Premultiplied transparency //Blend One One // Additive //Blend OneMinusDstColor One // Soft Additive //Blend DstColor Zero // Multiplicative //Blend DstColor SrcColor // 2x Multiplicative Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } Blend SrcAlpha One Cull Off Lighting Off ZWrite Off Fog{ Color(0,0,0,0) } CGPROGRAM #pragma target 5.0 #pragma vertex VSMAIN #pragma fragment PSMAIN #pragma geometry GSMAIN #include "UnityCG.cginc" struct Particle { //int index; float3 position; float3 velocity; //float size; //float age; //float normAge; //int type; }; StructuredBuffer<Particle> particles; // Variables from the properties. float4 _Color; float4 _SpeedColor; float _colorSwitch; Texture2D _ParticleTexture; SamplerState sampler_ParticleTexture; Texture2D _Ramp1Texture; SamplerState sampler_Ramp1Texture; float3 _worldPos; float _particleSize; float maxAge; float maxRad; struct VS_INPUT { uint vertexid : SV_VertexID; }; //-------------------------------------------------------------------------------- struct GS_INPUT { float4 position : SV_POSITION; float4 color : COLOR; //float size : TEXCOORD0; //float age : TEXCOORD1; //float type : TEXCOORD2; }; //-------------------------------------------------------------------------------- struct PS_INPUT { float4 position : SV_POSITION; float2 texcoords : TEXCOORD0; float4 color : COLOR; //float size : TEXCOORD1; //float age : TEXCOORD2; //float type : TEXCOORD3; }; //-------------------------------------------------------------------------------- GS_INPUT VSMAIN(in VS_INPUT input) { GS_INPUT output; output.position.xyz = particles[input.vertexid].position; output.position.w = 1.0; float speed = length(particles[input.vertexid].velocity); float lerpValue = clamp(speed / _colorSwitch, 0, 1); output.color = lerp(_Color, _SpeedColor, lerpValue); //output.age = particles[input.vertexid].normAge; //output.size = particles[input.vertexid].size; //output.type = particles[input.vertexid].type; return output; } // Dimensions // Length of tetrahedron edge : a. // The height of an regular tetrahedron : // h = sqrt(2 / 3) * a; // The radius of circumsphere : // R = sqrt(3 / 8) * a; // The height of the incenter O or // the radius of the insphere : // r = 1 / 3 * R or r = 1 / sqrt(24) * a; // The radius of midsphere(tangent to edges) : // rm = 1 / sqrt(8) * a; // The angle between two faces : ~70, 53 (yellow) // Angle(C, MAB, D) = degrees(atan(2 * sqrt(2))); // The angle between an edge and a face : ~54, 74 (green) // Angle(0, A, D) = degrees(atan(sqrt(2))); // The angle vertex - center - vertex: ~109.471 (violet) // Angle(A, 0, D) = degrees(acos(-1 / 3)); //void make_face(float3 a, float3 b, float3 c) //{ // float3 face_normal = normalize(cross(c - a, c - b)); // EmitVertex(); // gl_Position = mvpMatrix * vec4(b, 1.0); // color = face_color; // EmitVertex(); // gl_Position = mvpMatrix * vec4(c, 1.0); // color = face_color; // EmitVertex(); // EndPrimitive(); //} //-------------------------------------------------------------------------------- [maxvertexcount(12)] void GSMAIN(point GS_INPUT p[1], inout TriangleStream<PS_INPUT> triStream) { float4 pos = p[0].position*2; pos.w = 1; float4 col = p[0].color; //float4 pos = mul(UNITY_MATRIX_MVP, p[0].position); float scl = 20; float4 v[4]; float3 A, B, C, D; float4 a, b, c, d; A = _particleSize*float3(0, 0.612, 0); B = _particleSize*float3(0.5, -0.204, -0.288); C = _particleSize*float3(0, -0.204, 0.578); D = _particleSize*float3(-0.5, -0.204, -0.288); v[0] = pos + float4(A.x, A.y, A.z, 1); v[1] = pos + float4(B.x, B.y, B.z, 1); v[2] = pos + float4(C.x, C.y, C.z, 1); v[3] = pos + float4(D.x, D.y, D.z, 1); PS_INPUT pIn; a = mul(UNITY_MATRIX_MVP, v[0]); b = mul(UNITY_MATRIX_MVP, v[1]); c = mul(UNITY_MATRIX_MVP, v[2]); d = mul(UNITY_MATRIX_MVP, v[3]); pIn.position = a; pIn.texcoords = float2(0.0f, 1.0f); pIn.color = col; triStream.Append(pIn); pIn.position = c; pIn.texcoords = float2(1.0f, 1.0f); pIn.color = col; triStream.Append(pIn); pIn.position = b; pIn.texcoords = float2(0.0f, 0.0f); pIn.color = col; triStream.Append(pIn); triStream.RestartStrip(); pIn.position = a; pIn.texcoords = float2(0.0f, 1.0f); pIn.color = col; triStream.Append(pIn); pIn.position = b; pIn.texcoords = float2(1.0f, 1.0f); pIn.color = col; triStream.Append(pIn); pIn.position = d; pIn.texcoords = float2(0.0f, 0.0f); pIn.color = col; triStream.Append(pIn); triStream.RestartStrip(); pIn.position = a; pIn.texcoords = float2(0.0f, 1.0f); pIn.color = col; triStream.Append(pIn); pIn.position = d; pIn.texcoords = float2(1.0f, 1.0f); pIn.color = col; triStream.Append(pIn); pIn.position = c; pIn.texcoords = float2(0.0f, 0.0f); pIn.color = col; triStream.Append(pIn); triStream.RestartStrip(); pIn.position = b; pIn.texcoords = float2(0.0f, 1.0f); pIn.color = col; triStream.Append(pIn); pIn.position = c; pIn.texcoords = float2(1.0f, 1.0f); pIn.color = col; triStream.Append(pIn); pIn.position = d; pIn.texcoords = float2(0.0f, 0.0f); pIn.color = col; triStream.Append(pIn); triStream.RestartStrip(); //ref //pIn.size = p[0].size; //pIn.age = p[0].age; //pIn.type = p[0].type; } //-------------------------------------------------------------------------------- float4 PSMAIN(in PS_INPUT input) : COLOR { float4 col = input.color; float4 color = _ParticleTexture.Sample(sampler_ParticleTexture, input.texcoords); color *= col; return color; } //-------------------------------------------------------------------------------- ENDCG } } }