You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
5.2 KiB
162 lines
5.2 KiB
//========= Copyright 2016-2018, HTC Corporation. All rights reserved. =========== |
|
|
|
using UnityEngine; |
|
using HTC.UnityPlugin.Utility; |
|
|
|
namespace HTC.UnityPlugin.Pointer3D |
|
{ |
|
public class ProjectileGenerator : BaseRaySegmentGenerator |
|
{ |
|
public float velocity = 2f; |
|
public Vector3 gravity = Vector3.down; |
|
|
|
private float m_velocity; |
|
private Vector3 m_gravity; |
|
|
|
private float maxHalfJourney;// maximum distance if projectile angle equals to 45 degree using given velocity |
|
private float accY;// vertical accelerate |
|
|
|
private Vector3 systemY; |
|
private Vector3 systemX; |
|
|
|
private Vector3 v0;// initial velocity vector |
|
private float v0X;// initial horizontal velocity |
|
private float v0Y;// initial vertical velocity |
|
private bool isHeighPeek;// if included angle between v0 and systemX is larger then 45 degree |
|
private float halfJourney;// half maximum distance of projectile |
|
|
|
private float contactPointTime; |
|
private float nextContactPointTime; |
|
private float rayDistance; |
|
private float nextRayDistance; |
|
|
|
private void CalculateAcc() |
|
{ |
|
accY = -gravity.magnitude; |
|
} |
|
|
|
private void CalculatePeekDistanceMax() |
|
{ |
|
maxHalfJourney = 0.5f * velocity * velocity / Mathf.Abs(accY); |
|
} |
|
|
|
protected override void Start() |
|
{ |
|
base.Start(); |
|
CalculateAcc(); |
|
CalculatePeekDistanceMax(); |
|
} |
|
|
|
public override void ResetSegments() |
|
{ |
|
var velocityChanged = ChangeProp.Set(ref m_velocity, velocity); |
|
var gravityChanged = ChangeProp.Set(ref m_gravity, gravity); |
|
|
|
if (gravityChanged) |
|
{ |
|
CalculateAcc(); |
|
} |
|
|
|
if (velocityChanged || gravityChanged) |
|
{ |
|
CalculatePeekDistanceMax(); |
|
} |
|
|
|
systemY = -gravity; |
|
systemX = transform.forward; |
|
Vector3.OrthoNormalize(ref systemY, ref systemX); |
|
|
|
v0 = transform.forward * velocity; |
|
v0X = Vector3.Dot(v0, systemX); |
|
v0Y = Vector3.Dot(v0, systemY); |
|
isHeighPeek = Mathf.Abs(v0Y) > Mathf.Abs(v0X); |
|
|
|
contactPointTime = v0Y / accY; |
|
halfJourney = Mathf.Abs(contactPointTime); |
|
|
|
rayDistance = nextRayDistance = 0f; |
|
} |
|
|
|
public override bool NextSegment(out Vector3 direction, out float distance) |
|
{ |
|
if (isHeighPeek) |
|
{ |
|
if (contactPointTime < 0f) |
|
{ |
|
nextContactPointTime = 0f; |
|
} |
|
else |
|
{ |
|
nextContactPointTime = contactPointTime + halfJourney; |
|
} |
|
} |
|
else |
|
{ |
|
if (contactPointTime < 0f) |
|
{ |
|
nextContactPointTime = 0f; |
|
} |
|
else if (contactPointTime == 0f) |
|
{ |
|
if (halfJourney == 0f) |
|
{ |
|
nextContactPointTime = contactPointTime + maxHalfJourney * 0.3f; |
|
} |
|
else |
|
{ |
|
nextContactPointTime = contactPointTime + halfJourney; |
|
} |
|
} |
|
else |
|
{ |
|
// cap to maxHalfJourney to avoid small segment |
|
//nextContactPointTime = contactPointTime + maxHalfJourney; |
|
nextContactPointTime = contactPointTime + Mathf.Lerp(halfJourney, maxHalfJourney, 0.3f); |
|
} |
|
} |
|
|
|
var lastDistance = rayDistance; |
|
GetTangentLineIntersectDistance(contactPointTime, nextContactPointTime, out rayDistance, out nextRayDistance, out direction); |
|
distance = rayDistance + lastDistance; |
|
|
|
// shift for next iteration |
|
rayDistance = nextRayDistance; |
|
contactPointTime = nextContactPointTime; |
|
|
|
if (distance <= Pointer3DRaycaster.MIN_SEGMENT_DISTANCE) |
|
{ |
|
distance = Pointer3DRaycaster.MIN_SEGMENT_DISTANCE; |
|
//NextSegment(out direction, out distance); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
private void GetTangentLineIntersectDistance(float tA, float tB, out float dA, out float dB, out Vector3 directionA) |
|
{ |
|
if (tA == tB) |
|
{ |
|
dA = dB = 0f; |
|
|
|
directionA = (systemY * (accY * tA / v0X) + systemX).normalized; |
|
} |
|
else |
|
{ |
|
var vA = new Vector2(v0X * tA, 0.5f * accY * tA * tA); |
|
var vB = new Vector2(v0X * tB, 0.5f * accY * tB * tB); |
|
var mA = accY * tA / v0X; |
|
var mB = accY * tB / v0X; |
|
|
|
// C is intersect point between line through A and line through B |
|
var vC = default(Vector2); |
|
vC.x = (mA * vA.x - mB * vB.x - vA.y + vB.y) / (mA - mB); |
|
vC.y = mA * (vC.x - vA.x) + vA.y; |
|
|
|
dA = (vC - vA).magnitude; |
|
dB = (vC - vB).magnitude; |
|
|
|
directionA = (systemY * mA + systemX).normalized; |
|
} |
|
} |
|
} |
|
} |