Ok here is the problem am facing, I have an array of points of a bezier curve say {p0, c0}, {p1, c1}, {p2, c2}, {p3, c3}, where p are points, and c are the control points when in reality all 4 serve as points which form the curve.
Now this gives me a spline from p0 to p3. The array is populated with all the vertices which make up the spline, and am using a time step of say 60. So that gives me 60 vertices. Now in an update, or on the push of a button, or clicking on a vertex on the spline, I want to make that a control point on the line. So basically split the curve into two parts. In theory it is simply stiching two bezier curves together.
But am having some issues in the way that I populate the array, with the subdivisions made.
This is my code in C#, done in Unity. The drawing of the line and the bezier function is within the plugin "Vectrosity".
The MakeCurve function is a Vectrosity function and takes in the four vertices, and step (segments).
Everything executes fine. But when I change the line with the subdivisions. Things get weird and freaky.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Vectrosity;
public class Curve : MonoBehaviour {
public static Curve use ;
public static Camera m_mainCam ;
public Material m_lineMaterial ;
public GameObject m_anchorPrefab ;
public GameObject m_controlPrefab ;
private int oldWidth ;
private int m_maxSegments = 60 ;
private int m_minSegments = 12 ;
private int pointIndex = 0 ;
private VectorLine m_line ;
private VectorLine m_controlLine ;
private Vector2[] m_linePoints ;
// Used to hold vertices (where t == m_segments + 1)
// For drawing a smoother curve
private List<Vector2> m_curveAnchorPoints ;
private List<Vector2> m_curveControlPoints ;
// Used to hold vertices (where t < m_segments + 1)
// For instantiating anchor and control points
private List<Vector2> m_curveInterpolatedPoints ;
private List<Vector2> m_curveInterpolatedControlPoints ;
// For drawing the control lines
private Vector2[] m_drawCurvePoints ;
private Vector2[] m_drawCurveControlPoints ;
private Vector2[] m_drawPoints ;
private GameObject m_prevAnchorObject = null ;
void Start()
{
Intialize();
}
void Update()
{
if (Screen.width != oldWidth)
{
oldWidth = Screen.width;
ChangeResolution();
}
}
private void Intialize()
{
// Intialize Main Camera
m_mainCam = Camera.main;
// Initalize Curve Instance
use = this;
// Make the line object for the curve
m_linePoints = new Vector2[m_maxSegments+1] ;
SetLine() ;
// Set up initial curve points (Anchor & Control Points)
m_curveAnchorPoints = new List<Vector2>() ;
m_curveAnchorPoints.Clear() ;
m_curveControlPoints = new List<Vector2>() ;
m_curveControlPoints.Clear() ;
m_curveInterpolatedPoints = new List<Vector2>();
m_curveInterpolatedPoints.Clear();
m_curveInterpolatedControlPoints = new List<Vector2>();
m_curveInterpolatedControlPoints.Clear();
m_curveAnchorPoints.Add(new Vector2(Screen.width * 0.25f, Screen.height * 0.25f)) ;
m_curveControlPoints.Add(new Vector2(Screen.width * 0.125f, Screen.height * 0.5f)) ;
m_curveAnchorPoints.Add(new Vector2(Screen.width - Screen.width * 0.25f, Screen.height - Screen.height * 0.25f)) ;
m_curveControlPoints.Add(new Vector2(Screen.width - Screen.width * 0.125f, Screen.height * 0.5f)) ;
m_line.MakeCurve(m_curveAnchorPoints[0], m_curveControlPoints[0], m_curveAnchorPoints[1], m_curveControlPoints[1], m_maxSegments) ;
DrawLine(m_line) ;
// Get vertices for drawing min anchor and control points
for(int i = 0; i < m_maxSegments + 1; i += m_minSegments)
{
m_curveInterpolatedPoints.Add(m_line.points2[i]) ;
m_curveInterpolatedControlPoints.Add(new Vector2(m_line.points2[i].x + 50f, m_line.points2[i].y + 5f)) ;
}
// for(int i = 0; i < m_curveInterpolatedPoints.Count; i++)
// {
// Debug.Log(i + 1 + "th " + "Curve Point - " + m_curveInterpolatedPoints[i] + "\n" + "& Control Point - " + m_curveInterpolatedControlPoints[i]) ;
// }
SetDrawingArray();
m_controlLine = new VectorLine("Control Line", m_drawPoints, Color.red, m_lineMaterial, 2.0f) ;
DrawLine(m_controlLine) ;
}
private void SetLine()
{
m_line = new VectorLine("Curve", m_linePoints, m_lineMaterial, 5.0f, LineType.Continuous) ;
m_line.depth = 1 ;
}
private void DrawLine(VectorLine line)
{
line.Draw() ;
}
private void SetDrawingArray()
{
int len = m_curveInterpolatedPoints.Count + m_curveInterpolatedControlPoints.Count;
m_drawPoints = new Vector2[len];
m_drawCurvePoints = m_curveInterpolatedPoints.ToArray();
m_drawCurveControlPoints = m_curveInterpolatedControlPoints.ToArray();
int j = 0;
for(int i = 0; i < len; i += 2)
{
m_drawPoints[i] = m_drawCurvePoints[j];
m_drawPoints[i + 1] = m_drawCurveControlPoints[j];
j++;
}
for(int i = 0; i < len; i += 2)
{
AddControlObjects();
}
// for(int i = 0; i < len; i += 2)
// {
// Debug.Log("Curve Point - " + m_drawPoints[i] + "& Control Point - " + m_drawPoints[i + 1]) ;
// }
}
private void AddControlObjects()
{
GameObject anchorObject = Instantiate(m_anchorPrefab, m_mainCam.ScreenToViewportPoint(m_drawPoints[pointIndex]), Quaternion.identity) as GameObject ;
anchorObject.GetComponent<CurveControl>().m_objectNumber = pointIndex++ ;
GameObject controlObject = Instantiate(m_controlPrefab, m_mainCam.ScreenToViewportPoint(m_drawPoints[pointIndex]), Quaternion.identity) as GameObject ;
controlObject.GetComponent<CurveControl>().m_objectNumber = pointIndex++ ;
anchorObject.GetComponent<CurveControl>().m_controlObject01 = controlObject ;
anchorObject.GetComponent<CurveControl>().m_controlObject02 = m_prevAnchorObject ;
m_prevAnchorObject = anchorObject ;
}
public void UpdateLine(int objectNumber, Vector2 pos, GameObject go)
{
// Get previous position, so we can make the control point move with the anchor point
Vector2 oldPos = m_drawPoints[objectNumber] ;
m_drawPoints[objectNumber] = pos ;
int curveNumber = objectNumber / 4;
int curveIndex = curveNumber * 4;
m_line.MakeCurve(m_drawPoints[curveIndex], m_drawPoints[curveIndex + 1], m_drawPoints[curveIndex + 2], m_drawPoints[curveIndex + 3], m_minSegments, (m_minSegments + 1) * curveNumber);
// If it's an anchor point...
if (objectNumber % 2 == 0)
{
// Move control point also
m_drawPoints[objectNumber + 1] += pos - oldPos ;
go.GetComponent<CurveControl>().m_controlObject01.transform.position = m_mainCam.ScreenToViewportPoint(m_drawPoints[objectNumber + 1]) ;
// If it's not an end anchor point, move the next anchor/control points as well, and update the next curve
if (objectNumber > 0 && objectNumber < m_drawPoints.Length - 4)
{
m_drawPoints[objectNumber + 2] = pos ;
m_drawPoints[objectNumber + 3] += pos - oldPos ;
go.GetComponent<CurveControl>().m_controlObject02.transform.position = m_mainCam.ScreenToViewportPoint(m_drawPoints[objectNumber + 3]) ;
m_line.MakeCurve(m_drawPoints[curveIndex + 4], m_drawPoints[curveIndex + 5], m_drawPoints[curveIndex + 6], m_drawPoints[curveIndex + 7], m_minSegments, (curveNumber + 1) * (m_minSegments + 1));
}
}
DrawLine(m_line) ;
DrawLine(m_controlLine) ;
}
private void ChangeResolution()
{
VectorLine.SetCamera();
DrawLine(m_line);
DrawLine(m_controlLine);
var controlPointObjects = GameObject.FindGameObjectsWithTag("GameController");
foreach (var obj in controlPointObjects)
{
obj.transform.position = m_mainCam.ScreenToViewportPoint(m_drawPoints[obj.GetComponent<CurveControl>().m_objectNumber]);
}
}
}