改变抛物线的方向以跟随鼠标拖动
Change parabola's direction to follow mouse drag
我正在尝试计算如果一个物体沿着水面被拖动,留在水中的抛物线轨迹。
我认为将轨迹方法与焦点、顶点和准线一起使用是可行的方法。这适用于垂直和水平运动(取决于准线轴)但是随着准线不断移动其轴方向我被卡住了。
这就是我现在的(为垂直移动而写)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(LineRenderer))]
public class Parabola : MonoBehaviour {
public GameObject pointD, pointF, pointM;
public LineRenderer line;
public Vector3 mouse=Vector3.one, prev;
public Vector3 directrix;
public Vector3 focusPoint, directrixPointMid, directrixPointL, directrixPointR;
public float directrixLength;
public int resolution;
public Vector3 focalLine;
public float focalLenght;
public Vector3 p;
public List<Vector3> points = new List<Vector3>();
void Start ()
{
prev = mouse;
line = GetComponent<LineRenderer>();
line.positionCount = resolution;
}
void Update ()
{
if(Input.GetMouseButton(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if(Physics.Raycast(ray, out hit, Mathf.Infinity, 1<<LayerMask.NameToLayer("Plane")))
{
mouse = new Vector3(hit.point.x,0,hit.point.z);
if(prev != mouse)
{
focalLine = prev - mouse;
focusPoint = mouse + focalLine.normalized * focalLenght;
directrixPointMid = mouse +(-focalLine.normalized * focalLenght);
directrix = Vector3.Cross(directrixPointMid-focusPoint, Vector3.up);
directrixPointL = directrixPointMid +(directrix.normalized * (directrixLength/2));
directrixPointR = directrixPointMid +(-directrix.normalized * (directrixLength/2));
Debug.DrawRay(mouse, focalLine.normalized*10,Color.green);
Debug.DrawRay(directrixPointR, directrix.normalized*directrixLength,Color.red);
pointD.transform.position = directrixPointMid;
pointF.transform.position = focusPoint;
pointM.transform.position = mouse;
prev = mouse;
}
}
points = new List<Vector3>();
for(float i = -directrixLength/2; i<=directrixLength/2; i+=directrixLength/resolution)
{
//float angle = Vector3.Angle(Vector3.forward,focalLine);
float z = 1/(2*(focusPoint.z-directrixPointMid.z))*Mathf.Pow((Mathf.Abs(directrixPointMid.x)+i)-focusPoint.x,2)+0.5f*(focusPoint.z+directrixPointMid.z);
float x = directrixPointMid.x+i;
p = new Vector3(x,1,z);
//p = new Vector3(x*Mathf.Cos(angle)-z*Mathf.Sin(angle),1,x*Mathf.Sin(angle) + z*Mathf.Cos(angle));
//p.z = 2*p.x + Mathf.Sin(p.x);
//p = new Vector3(p.x*Mathf.Cos(angle)-p.z*Mathf.Sin(angle),1,p.x*Mathf.Sin(angle) + p.z*Mathf.Cos(angle));
points.Add(p);
}
line.SetPositions(points.ToArray());
}
}
}
有一些已注释掉的尝试,但没有任何效果。
我将我的设置更改为使用 y = x^2 并将我的所有坐标设为拖动方向的局部坐标。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Parabola : MonoBehaviour {
public GameObject linePrefab, pointV;
public float offset, amp, speed;
public int freq;
public float directrixLength;
public int resolution;
private Vector3 mouse, prev;
private Vector3 directrix;
private Vector3 focusPoint, directrixPointMid, directrixPointL, directrixPointR;
private Vector3 focalLine;
private Vector3 p;
private List<List<Vector3>> pointsR = new List<List<Vector3>>();
private List<LineRenderer> lines = new List<LineRenderer>();
public Renderer render;
void Start ()
{
render.material.SetInt("_Length", resolution);
render.material.SetVectorArray("_Points", new Vector4[resolution]);
prev = mouse;
int i = 0;
while(i <= freq)
{
GameObject g = Instantiate(linePrefab);
g.transform.SetParent(transform);
g.transform.localPosition = Vector3.zero;
LineRenderer line = g.GetComponent<LineRenderer>();
line.positionCount = resolution;
lines.Add(line);
List<Vector3> lR = new List<Vector3>();
pointsR.Add(lR);
i++;
}
}
void FixedUpdate ()
{
if(Input.GetMouseButton(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if(Physics.Raycast(ray, out hit, Mathf.Infinity, 1<<LayerMask.NameToLayer("Plane")))
{
mouse = new Vector3(hit.point.x,0,hit.point.z);
StopCoroutine(CalculateParabola(mouse));
StartCoroutine(CalculateParabola(mouse));
transform.position = mouse;
transform.forward = -focalLine;
}
}
}
IEnumerator CalculateParabola(Vector3 v)
{
while(prev != v)
{
focalLine = prev - v;
//calculate a parabola for each n in frequency, make it go wider the higher n is
for(int n=0; h<=freq; n++)
{
pointsR[n] = new List<Vector3>();
float s = Vector3.Distance(prev.normalized,v.normalized)*speed;
for(float i = -directrixLength/2; i<=(directrixLength+1)/2; i+=directrixLength/resolution)
{
p.x = pointV.transform.localPosition.x+(i*(freq-n+Time.fixedDeltaTime*s));
p.z = ((amp*(freq-n))*(Time.fixedDeltaTime*s))*-Mathf.Pow(p.x,2)+(1+offset*n);
pointsR[n].Add(p);
}
lines[h].SetPositions(pointsR[n].ToArray());
//attempt to translate the points to a shader, only for the first parabola for now
Vector4[] renderPoints = new Vector4[resolution];
for(int i=0; i<resolution; i++)
{
renderPoints[i] = transform.TransformPoint(pointsR[0][i]) - render.transform.position;
}
render.material.SetVectorArray("_Points", renderPoints);
}
yield return new WaitForSeconds(0.1f);
prev = v;
}
}
}
我正在尝试计算如果一个物体沿着水面被拖动,留在水中的抛物线轨迹。 我认为将轨迹方法与焦点、顶点和准线一起使用是可行的方法。这适用于垂直和水平运动(取决于准线轴)但是随着准线不断移动其轴方向我被卡住了。
这就是我现在的(为垂直移动而写)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(LineRenderer))]
public class Parabola : MonoBehaviour {
public GameObject pointD, pointF, pointM;
public LineRenderer line;
public Vector3 mouse=Vector3.one, prev;
public Vector3 directrix;
public Vector3 focusPoint, directrixPointMid, directrixPointL, directrixPointR;
public float directrixLength;
public int resolution;
public Vector3 focalLine;
public float focalLenght;
public Vector3 p;
public List<Vector3> points = new List<Vector3>();
void Start ()
{
prev = mouse;
line = GetComponent<LineRenderer>();
line.positionCount = resolution;
}
void Update ()
{
if(Input.GetMouseButton(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if(Physics.Raycast(ray, out hit, Mathf.Infinity, 1<<LayerMask.NameToLayer("Plane")))
{
mouse = new Vector3(hit.point.x,0,hit.point.z);
if(prev != mouse)
{
focalLine = prev - mouse;
focusPoint = mouse + focalLine.normalized * focalLenght;
directrixPointMid = mouse +(-focalLine.normalized * focalLenght);
directrix = Vector3.Cross(directrixPointMid-focusPoint, Vector3.up);
directrixPointL = directrixPointMid +(directrix.normalized * (directrixLength/2));
directrixPointR = directrixPointMid +(-directrix.normalized * (directrixLength/2));
Debug.DrawRay(mouse, focalLine.normalized*10,Color.green);
Debug.DrawRay(directrixPointR, directrix.normalized*directrixLength,Color.red);
pointD.transform.position = directrixPointMid;
pointF.transform.position = focusPoint;
pointM.transform.position = mouse;
prev = mouse;
}
}
points = new List<Vector3>();
for(float i = -directrixLength/2; i<=directrixLength/2; i+=directrixLength/resolution)
{
//float angle = Vector3.Angle(Vector3.forward,focalLine);
float z = 1/(2*(focusPoint.z-directrixPointMid.z))*Mathf.Pow((Mathf.Abs(directrixPointMid.x)+i)-focusPoint.x,2)+0.5f*(focusPoint.z+directrixPointMid.z);
float x = directrixPointMid.x+i;
p = new Vector3(x,1,z);
//p = new Vector3(x*Mathf.Cos(angle)-z*Mathf.Sin(angle),1,x*Mathf.Sin(angle) + z*Mathf.Cos(angle));
//p.z = 2*p.x + Mathf.Sin(p.x);
//p = new Vector3(p.x*Mathf.Cos(angle)-p.z*Mathf.Sin(angle),1,p.x*Mathf.Sin(angle) + p.z*Mathf.Cos(angle));
points.Add(p);
}
line.SetPositions(points.ToArray());
}
}
}
有一些已注释掉的尝试,但没有任何效果。
我将我的设置更改为使用 y = x^2 并将我的所有坐标设为拖动方向的局部坐标。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Parabola : MonoBehaviour {
public GameObject linePrefab, pointV;
public float offset, amp, speed;
public int freq;
public float directrixLength;
public int resolution;
private Vector3 mouse, prev;
private Vector3 directrix;
private Vector3 focusPoint, directrixPointMid, directrixPointL, directrixPointR;
private Vector3 focalLine;
private Vector3 p;
private List<List<Vector3>> pointsR = new List<List<Vector3>>();
private List<LineRenderer> lines = new List<LineRenderer>();
public Renderer render;
void Start ()
{
render.material.SetInt("_Length", resolution);
render.material.SetVectorArray("_Points", new Vector4[resolution]);
prev = mouse;
int i = 0;
while(i <= freq)
{
GameObject g = Instantiate(linePrefab);
g.transform.SetParent(transform);
g.transform.localPosition = Vector3.zero;
LineRenderer line = g.GetComponent<LineRenderer>();
line.positionCount = resolution;
lines.Add(line);
List<Vector3> lR = new List<Vector3>();
pointsR.Add(lR);
i++;
}
}
void FixedUpdate ()
{
if(Input.GetMouseButton(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if(Physics.Raycast(ray, out hit, Mathf.Infinity, 1<<LayerMask.NameToLayer("Plane")))
{
mouse = new Vector3(hit.point.x,0,hit.point.z);
StopCoroutine(CalculateParabola(mouse));
StartCoroutine(CalculateParabola(mouse));
transform.position = mouse;
transform.forward = -focalLine;
}
}
}
IEnumerator CalculateParabola(Vector3 v)
{
while(prev != v)
{
focalLine = prev - v;
//calculate a parabola for each n in frequency, make it go wider the higher n is
for(int n=0; h<=freq; n++)
{
pointsR[n] = new List<Vector3>();
float s = Vector3.Distance(prev.normalized,v.normalized)*speed;
for(float i = -directrixLength/2; i<=(directrixLength+1)/2; i+=directrixLength/resolution)
{
p.x = pointV.transform.localPosition.x+(i*(freq-n+Time.fixedDeltaTime*s));
p.z = ((amp*(freq-n))*(Time.fixedDeltaTime*s))*-Mathf.Pow(p.x,2)+(1+offset*n);
pointsR[n].Add(p);
}
lines[h].SetPositions(pointsR[n].ToArray());
//attempt to translate the points to a shader, only for the first parabola for now
Vector4[] renderPoints = new Vector4[resolution];
for(int i=0; i<resolution; i++)
{
renderPoints[i] = transform.TransformPoint(pointsR[0][i]) - render.transform.position;
}
render.material.SetVectorArray("_Points", renderPoints);
}
yield return new WaitForSeconds(0.1f);
prev = v;
}
}
}