forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   Уроки (http://forum.boolean.name/forumdisplay.php?f=145)
-   -   Spline (http://forum.boolean.name/showthread.php?t=18659)

WISHMASTER35 28.10.2013 22:55

Spline
 
Вложений: 1
Написал алгоритм CatmullRom

Основной класс
Код:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class SplineUtils {
       
        private const int stepCount = 10;
       
        public static Vector3[] CreateSpline(Vector3[] points) {
                List<Vector3> result = new List<Vector3>();
                int last = points.Length - 1;
                for (int i = 0; i < points.Length-1; i++) {
                        int previous = Mathf.Clamp(i-1, 0, last);
            int start = i;
            int end = Mathf.Clamp(i+1, 0, last);
            int next = Mathf.Clamp(end+1, 0, last);
                       
                        for (int step = 0; step <= stepCount; step++) {
                                Vector3 point = SplineUtils.CatmullRom(points[previous], points[start], points[end], points[next], (float) step/stepCount);
                    result.Add( point );       
            }
                }
                return result.ToArray();
        }
       
        public static Vector3 GetPosition(Vector3[] points, float t) {
                t = Mathf.Clamp01(t) * Length(points);
                int last = points.Length - 1;
                float tBegin = 0, tEnd = 0;
                for (int i = 0; i < points.Length-1; i++) {
                        int previous = Mathf.Clamp(i-1, 0, last);
            int start = i;
            int end = Mathf.Clamp(i+1, 0, last);
            int next = Mathf.Clamp(end+1, 0, last);
                       
                        tEnd = tBegin + Length(points[previous], points[start], points[end], points[next]);
                        if(tBegin<=t && t<=tEnd) {
                                t -= tBegin;
                                t /= (tEnd-tBegin);
                                return CatmullRom(points[previous], points[start], points[end], points[next], t);
                        }
                        tBegin = tEnd;
                }
                return Vector3.zero;
        }
       
        public static float Length(Vector3[] points) {
                float length = 0;
                int last = points.Length - 1;
                for (int i = 0; i < points.Length-1; i++) {
                        int previous = Mathf.Clamp(i-1, 0, last);
            int start = i;
            int end = Mathf.Clamp(i+1, 0, last);
            int next = Mathf.Clamp(end+1, 0, last);
                       
                        length += Length(points[previous], points[start], points[end], points[next]);
                }
                return length;
        }
       
        public static float Length(Vector3 previous, Vector3 start, Vector3 end, Vector3 next) {
                Vector3 a = start;
                float length = 0;
                for (int i = 1; i <= stepCount; i++) {
                        Vector3 b = CatmullRom(previous, start, end, next, (float) i/stepCount);
                length += Vector3.Distance( a, b );
                        a = b;
        }
                return length;
        }
       
        public static Vector3 CatmullRom(Vector3 previous, Vector3 start, Vector3 end, Vector3 next, float t) {
                t = Mathf.Clamp01(t);
        float t2 = t * t;
        float t3 = t * t * t;
        return previous * (-0.5f * t3 + t2 - 0.5f * t) +
              start    * ( 1.5f * t3 - 2.5f * t2 + 1.0f) +
              end      * (-1.5f * t3 + 2.0f * t2 + 0.5f * t) +
              next    * ( 0.5f * t3 - 0.5f * t2);
        }
       
       
}



Скрипт для демонстрации
Код:

using UnityEngine;
using System.Collections;

public class Spline : MonoBehaviour {
       
        public float time = 0;

        void OnDrawGizmos() {
                Vector3[] points = GetPoints();
                Vector3[] result = SplineUtils.CreateSpline(points);
                for(int i=0; i<result.Length-1; i++) {
                        Vector3 p1 = result[i];
                        Vector3 p2 = result[i+1];
                        Gizmos.color = Color.red;
                        Gizmos.DrawLine(p1, p2);
                }
               
                Gizmos.color = Color.red;
                Gizmos.DrawSphere( SplineUtils.GetPosition(points, time/10), 0.2f );
        }
       
        private Vector3[] GetPoints() {
                Vector3[] points = new Vector3[ transform.childCount ];
                for(int i=0; i<points.Length; i++) {
                        points[i] = transform.GetChild(i).transform.position;
                }
                return points;
        }
       
}



И маленький класс для выбора нода щелчком мыши. Использует UnityEditor и HandleUtility.GetHandleSize поэтому проект с ним не сбилдится.
Код:

using UnityEditor;
using UnityEngine;
using System.Collections;

public class SplineNode : MonoBehaviour {
       
        void OnDrawGizmos() {
                float size = HandleUtility.GetHandleSize(transform.position) * 0.1f;
                Gizmos.color = Color.yellow;
                Gizmos.DrawSphere(transform.position,  size);
        }
       
}



Часовой пояс GMT +4, время: 20:46.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot