Unity3D教你制作Bezier和Spine曲线编辑器三
来源:互联网 发布:网络作家收入怎么收税 编辑:程序博客网 时间:2024/06/15 06:14
继续接着介绍曲线编辑器的制作,上篇博客介绍了关于Bezier曲线的制作,接下来给读者介绍Spine B样条曲线之作。
如果要创建复杂的曲线,我们需要连接多个曲线,这样的构造称为样条。让我们通过复制Bezier曲线代码来创建一个,将类型更改为BezierSpline。
using UnityEngine;public class BezierSpline : MonoBehaviour {public Vector3[] points;public Vector3 GetPoint (float t) {return transform.TransformPoint(Bezier.GetPoint(points[0], points[1], points[2], points[3], t));}public Vector3 GetVelocity (float t) {return transform.TransformPoint(Bezier.GetFirstDerivative(points[0], points[1], points[2], points[3], t)) - transform.position;}public Vector3 GetDirection (float t) {return GetVelocity(t).normalized;}public void Reset () {points = new Vector3[] {new Vector3(1f, 0f, 0f),new Vector3(2f, 0f, 0f),new Vector3(3f, 0f, 0f),new Vector3(4f, 0f, 0f)};}}
另外,我们还通过复制和调整Bezier曲线Inspector的代码来创建一个编辑器,然后我们可以创建一个spline对象并编辑它,就像一条曲线。
using UnityEditor;using UnityEngine;[CustomEditor(typeof(BezierSpline))]public class BezierSplineInspector : Editor {private const int lineSteps = 10;private const float directionScale = 0.5f;private BezierSpline spline;private Transform handleTransform;private Quaternion handleRotation;private void OnSceneGUI () {spline = target as BezierSpline;handleTransform = spline.transform;handleRotation = Tools.pivotRotation == PivotRotation.Local ?handleTransform.rotation : Quaternion.identity;Vector3 p0 = ShowPoint(0);Vector3 p1 = ShowPoint(1);Vector3 p2 = ShowPoint(2);Vector3 p3 = ShowPoint(3);Handles.color = Color.gray;Handles.DrawLine(p0, p1);Handles.DrawLine(p2, p3);ShowDirections();Handles.DrawBezier(p0, p3, p1, p2, Color.white, null, 2f);}private void ShowDirections () {Handles.color = Color.green;Vector3 point = spline.GetPoint(0f);Handles.DrawLine(point, point + spline.GetDirection(0f) * directionScale);for (int i = 1; i <= lineSteps; i++) {point = spline.GetPoint(i / (float)lineSteps);Handles.DrawLine(point, point + spline.GetDirection(i / (float)lineSteps) *
directionScale);}}private Vector3 ShowPoint (int index) {Vector3 point = handleTransform.TransformPoint(spline.points[index]);EditorGUI.BeginChangeCheck();point = Handles.DoPositionHandle(point, handleRotation);if (EditorGUI.EndChangeCheck()) {Undo.RecordObject(spline, "Move Point");EditorUtility.SetDirty(spline);spline.points[index] = handleTransform.InverseTransformPoint(point);}return point;}}
这样,让我们向BezierSpline添加一个方法,以向样条添加另一条曲线,因为我们希望spline是连续的,上一条曲线的最后一点与下一条曲线的第
一个点是一样的。所以每条额外的曲线又增加了三个点。
public void AddCurve () {Vector3 point = points[points.Length - 1];Array.Resize(ref points, points.Length + 3);point.x += 1f;points[points.Length - 3] = point;point.x += 1f;points[points.Length - 2] = point;point.x += 1f;points[points.Length - 1] = point;}
我们使用Array.Resize创建一个更大的数组来保存新点,它在system命名空间内,因此我们应该声明我们在脚本
的顶部使用它。
using UnityEngine;using System;
为了能够添加一条曲线,我们必须在spline的检查器中添加一个按钮,我们可以通过重写BezierSplineInspector的OnInspectorGUI方法来定
制组件的统一使用。注意,这不是一个特殊的统一方法,它依赖于继承。
另外,我们调用DrawDefaultInspector方法。然后我们使用GUILayout来绘制一个按钮,点击添加一条曲线。
public override void OnInspectorGUI () {DrawDefaultInspector();spline = target as BezierSpline;if (GUILayout.Button("Add Curve")) {Undo.RecordObject(spline, "Add Curve");spline.AddCurve();EditorUtility.SetDirty(spline);}}
当然,我们仍然只看到第一条曲线。所以我们调整BezierSplineInspector,让它在所有曲线上循环。
private void OnSceneGUI () {spline = target as BezierSpline;handleTransform = spline.transform;handleRotation = Tools.pivotRotation == PivotRotation.Local ?handleTransform.rotation : Quaternion.identity;Vector3 p0 = ShowPoint(0);for (int i = 1; i < spline.points.Length; i += 3) {Vector3 p1 = ShowPoint(i);Vector3 p2 = ShowPoint(i + 1);Vector3 p3 = ShowPoint(i + 2);Handles.color = Color.gray;Handles.DrawLine(p0, p1);Handles.DrawLine(p2, p3);Handles.DrawBezier(p0, p3, p1, p2, Color.white, null, 2f);p0 = p3;}ShowDirections();}
现在,我们可以看到所有的曲线,但是方向线只增加到第一个。这是因为BezierSpline的方法仍然只适用于第一个曲线。是时候改变
这种状况了。
为了覆盖整个样条,从0到1,我们需要首先求出我们在哪个曲线上。我们可以得到曲线的指数乘以t乘以曲线的数量然后丢弃分数。让我们
添加一个曲率属性来简化它。
public int CurveCount {get {return (points.Length - 1) / 3;}}
之后,我们可以将t减少到小数部分来得到曲线的内插值。为了得到实际的点,我们必须将曲线指数乘以3。
然而,当初始t = 1时,这将会失败。在这种情况下,我们可以把它设置成最后一条曲线。
public Vector3 GetPoint (float t) {int i;if (t >= 1f) {t = 1f;i = points.Length - 4;}else {t = Mathf.Clamp01(t) * CurveCount;i = (int)t;t -= i;i *= 3;}return transform.TransformPoint(Bezier.GetPoint(points[i], points[i + 1], points[i + 2], points[i + 3], t));}public Vector3 GetVelocity (float t) {int i;if (t >= 1f) {t = 1f;i = points.Length - 4;}else {t = Mathf.Clamp01(t) * CurveCount;i = (int)t;t -= i;i *= 3;}return transform.TransformPoint(Bezier.GetFirstDerivative(points[i], points[i + 1], points[i + 2], points[i + 3], t)) - transform.position;}
我们现在看到了整个样条的方向线,但是我们可以通过确保每个曲线段得到相同数量的线来改进可视化。幸运的是,很容易更改
BezierSplineInspector,显示方向,所以它使用BezierSpline,曲率决定画多少线。
private const int stepsPerCurve = 10;private void ShowDirections () {Handles.color = Color.green;Vector3 point = spline.GetPoint(0f);Handles.DrawLine(point, point + spline.GetDirection(0f) * directionScale);int steps = stepsPerCurve * spline.CurveCount;for (int i = 1; i <= steps; i++) {point = spline.GetPoint(i / (float)steps);Handles.DrawLine(point, point + spline.GetDirection(i / (float)steps) * directionScale);}}
让更新ShowPoint,这样它显示一个按钮而不是一个位置句柄。这个按钮看起来像一个白色的点,当点击将会变成活动的点。
然后,如果point的索引与所选的索引匹配,那么我们只显示该位置句柄,这是我们在- 1中初始化的,所以默认情况下没有选择。
private const float handleSize = 0.04f;private const float pickSize = 0.06f;private int selectedIndex = -1;private Vector3 ShowPoint (int index) {Vector3 point = handleTransform.TransformPoint(spline.points[index]);Handles.color = Color.white;if (Handles.Button(point, handleRotation, handleSize, pickSize, Handles.DotCap)) {selectedIndex = index;}if (selectedIndex == index) {EditorGUI.BeginChangeCheck();point = Handles.DoPositionHandle(point, handleRotation);if (EditorGUI.EndChangeCheck()) {Undo.RecordObject(spline, "Move Point");EditorUtility.SetDirty(spline);spline.points[index] = handleTransform.InverseTransformPoint(point);}}return point;}
这是可行的,但很难让这些点有一个比较理想的尺寸,根据你所处的规模,他们可能要么太大,要么太小,如果我们能保持圆点的屏幕
尺寸不变就好了,就像位置句柄总是有相同的屏幕大小一样。我们可以通过在HandleUtility.GetHandleSize保理。这个方法为我们提供
了一个固定的屏幕尺寸,在世界范围内的任何一点。
float size = HandleUtility.GetHandleSize(point);Handles.color = Color.white;if (Handles.Button(point, handleRotation, size * handleSize, size * pickSize, Handles.DotCap)) {selectedIndex = index;}
代码下载地址:链接:http://pan.baidu.com/s/1gfrJVrl 密码:ft1o 中的编号03的包。
在下篇博客中介绍控制点的制作。。。。
- Unity3D教你制作Bezier和Spine曲线编辑器三
- Unity3D教你制作Bezier和Spine曲线编辑器一
- Unity3D教你制作Bezier和Spine曲线编辑器一
- Unity3D教你制作Bezier和Spine曲线编辑器二
- Unity3D教你制作Bezier和Spine曲线编辑器四
- Unity3D教你制作Bezier和Spine曲线编辑器总结
- bezier曲线和bezier曲面
- 【计算机图形学】三、bezier曲线的生成
- Unity3d下 spine 2D骨骼制作
- Bezier曲线:
- bezier 曲线
- Bezier曲线
- Bezier曲线
- (28)Bezier曲线和曲面
- OpenGL中如何绘制Bezier曲线和NURBS曲线
- OpenGL中如何绘制Bezier曲线和NURBS曲线
- Bezier曲线和B样条曲线的一些资料
- Bezier曲线生成算法
- Windows下安装Docker
- Cento安装mysql出错 file /usr/share/mysql/czech/errmsg.sys from install of MySQL-server-5.5.31-2.el6.i6
- jquery判断checkbox是否选中的3种方法
- STN系列之Spatial Transformer Networks
- 单元测试MAVEN引入junit的jar包不起作用
- Unity3D教你制作Bezier和Spine曲线编辑器三
- 资讯精选 | 浅析机器视觉测试系统市场现状
- 二叉树最大路径和
- python笔记----解构和封装
- 基于Innobackupex的增备及恢复
- CentOS 7 64位下MySQL5.7卸载改成MySQL5.6版本(YUM)
- java生成验证码两种方法
- UWP 手绘视频创作工具 “来画Pro” 技术分享系列
- HTML5新特性:FileReader 和 FormData