您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

238 行
8.0 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Unity.UIWidgets.ui {
class TessellationKey : IEquatable<TessellationKey> {
public readonly float x2;
public readonly float y2;
public readonly float x3;
public readonly float y3;
public readonly float x4;
public readonly float y4;
public readonly float tessTol;
public TessellationKey(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4,
float tessTol) {
this.x2 = x2 - x1;
this.y2 = y2 - y1;
this.x3 = x3 - x1;
this.y3 = y3 - y1;
this.x4 = x4 - x1;
this.y4 = y4 - y1;
this.tessTol = tessTol;
}
public bool Equals(TessellationKey other) {
if (ReferenceEquals(null, other)) {
return false;
}
if (ReferenceEquals(this, other)) {
return true;
}
return this.x2.Equals(other.x2) && this.y2.Equals(other.y2) && this.x3.Equals(other.x3) &&
this.y3.Equals(other.y3) && this.x4.Equals(other.x4) && this.y4.Equals(other.y4) &&
this.tessTol.Equals(other.tessTol);
}
public override bool Equals(object obj) {
if (ReferenceEquals(null, obj)) {
return false;
}
if (ReferenceEquals(this, obj)) {
return true;
}
if (obj.GetType() != this.GetType()) {
return false;
}
return this.Equals((TessellationKey) obj);
}
public override int GetHashCode() {
unchecked {
var hashCode = this.x2.GetHashCode();
hashCode = (hashCode * 397) ^ this.y2.GetHashCode();
hashCode = (hashCode * 397) ^ this.x3.GetHashCode();
hashCode = (hashCode * 397) ^ this.y3.GetHashCode();
hashCode = (hashCode * 397) ^ this.x4.GetHashCode();
hashCode = (hashCode * 397) ^ this.y4.GetHashCode();
hashCode = (hashCode * 397) ^ this.tessTol.GetHashCode();
return hashCode;
}
}
public static bool operator ==(TessellationKey left, TessellationKey right) {
return Equals(left, right);
}
public static bool operator !=(TessellationKey left, TessellationKey right) {
return !Equals(left, right);
}
public override string ToString() {
return $"TessellationKey(" +
$"x2: {this.x2}, " +
$"y2: {this.y2}, " +
$"x3: {this.x3}, " +
$"y3: {this.y3}, " +
$"x4: {this.x4}, " +
$"y4: {this.y4}, " +
$"tessTol: {this.tessTol})";
}
}
class TessellationInfo {
public readonly TessellationKey key;
public readonly List<Vector2> points;
long _timeToLive;
public TessellationInfo(TessellationKey key, List<Vector2> points, int timeToLive = 5) {
this.points = points;
this.key = key;
this.touch(timeToLive);
}
public long timeToLive {
get { return this._timeToLive; }
}
public void touch(long timeTolive = 5) {
this._timeToLive = timeTolive + MeshGenerator.frameCount;
}
}
static class TessellationGenerator {
static readonly Dictionary<TessellationKey, TessellationInfo> _tessellations =
new Dictionary<TessellationKey, TessellationInfo>();
static long _frameCount = 0;
public static long frameCount {
get { return _frameCount; }
}
public static int tessellationCount {
get { return _tessellations.Count; }
}
public static void tickNextFrame() {
_frameCount++;
var keysToRemove = _tessellations.Values.Where(info => info.timeToLive < _frameCount)
.Select(info => info.key).ToList();
foreach (var key in keysToRemove) {
_tessellations.Remove(key);
}
}
public static List<PathPoint> tessellateBezier(float x1, float y1, float x2, float y2,
float x3, float y3, float x4, float y4, float tessTol) {
var key = new TessellationKey(x1, y1, x2, y2, x3, y3, x4, y4, tessTol);
_tessellations.TryGetValue(key, out var tessellationInfo);
if (tessellationInfo != null) {
tessellationInfo.touch();
return _toPathPoints(tessellationInfo.points, x1, y1);
}
var points = _tessellateBezier(x1, y1, x2, y2, x3, y3, x4, y4, tessTol);
_tessellations[key] = new TessellationInfo(key, points);
return _toPathPoints(points, x1, y1);
}
static List<PathPoint> _toPathPoints(List<Vector2> points, float x1, float y1) {
var pathPoints = new List<PathPoint>(points.Count);
foreach (var point in points) {
pathPoints.Add(new PathPoint {
x = point.x + x1,
y = point.y + y1,
});
}
return pathPoints;
}
struct _StackData {
public float x1;
public float y1;
public float x2;
public float y2;
public float x3;
public float y3;
public float x4;
public float y4;
public int level;
}
static List<Vector2> _tessellateBezier(
float x1, float y1, float x2, float y2,
float x3, float y3, float x4, float y4,
float tessTol) {
x2 = x2 - x1;
y2 = y2 - y1;
x3 = x3 - x1;
y3 = y3 - y1;
x4 = x4 - x1;
y4 = y4 - y1;
var points = new List<Vector2>();
var stack = new Stack<_StackData>();
stack.Push(new _StackData {
x1 = 0, y1 = 0, x2 = x2, y2 = y2, x3 = x3, y3 = y3, x4 = x4, y4 = y4, level = 0,
});
while (stack.Count > 0) {
var stackData = stack.Pop();
x1 = stackData.x1;
y1 = stackData.y1;
x2 = stackData.x2;
y2 = stackData.y2;
x3 = stackData.x3;
y3 = stackData.y3;
x4 = stackData.x4;
y4 = stackData.y4;
int level = stackData.level;
float dx = x4 - x1;
float dy = y4 - y1;
float d2 = Mathf.Abs((x2 - x4) * dy - (y2 - y4) * dx);
float d3 = Mathf.Abs((x3 - x4) * dy - (y3 - y4) * dx);
if ((d2 + d3) * (d2 + d3) <= tessTol * (dx * dx + dy * dy)) {
points.Add(new Vector2(x4, y4));
continue;
}
float x12 = (x1 + x2) * 0.5f;
float y12 = (y1 + y2) * 0.5f;
float x23 = (x2 + x3) * 0.5f;
float y23 = (y2 + y3) * 0.5f;
float x34 = (x3 + x4) * 0.5f;
float y34 = (y3 + y4) * 0.5f;
float x123 = (x12 + x23) * 0.5f;
float y123 = (y12 + y23) * 0.5f;
float x234 = (x23 + x34) * 0.5f;
float y234 = (y23 + y34) * 0.5f;
float x1234 = (x123 + x234) * 0.5f;
float y1234 = (y123 + y234) * 0.5f;
if (level < 10) {
stack.Push(new _StackData {
x1 = x1234, y1 = y1234, x2 = x234, y2 = y234, x3 = x34, y3 = y34, x4 = x4, y4 = y4,
level = level + 1,
});
stack.Push(new _StackData {
x1 = x1, y1 = y1, x2 = x12, y2 = y12, x3 = x123, y3 = y123, x4 = x1234, y4 = y1234,
level = level + 1,
});
}
}
return points;
}
}
}