Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   forum.boolean.name > Программирование игр для компьютеров > Unity > Уроки

Ответ
 
Опции темы
Старый 28.10.2013, 22:55   #1
WISHMASTER35
Бывалый
 
Аватар для WISHMASTER35
 
Регистрация: 21.12.2008
Адрес: UA
Сообщений: 878
Написано 105 полезных сообщений
(для 357 пользователей)
Spline

Написал алгоритм 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);
	}
	
}
Миниатюры
Нажмите на изображение для увеличения
Название: Безымянный.png
Просмотров: 1058
Размер:	48.9 Кб
ID:	19840  
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
pax (29.10.2013)
Ответ


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


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


vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com