10using System.Collections.Generic;
16 #pragma warning disable 0649
17 [Tooltip(
"Each pinch detector can draw one line at a time.")]
22 private Material _material;
28 private float _smoothingDelay = 0.01f;
31 private float _drawRadius = 0.002f;
34 private int _drawResolution = 8;
37 private float _minSegmentLength = 0.005f;
38 #pragma warning restore 0649
40 private DrawState[] _drawStates;
61 _drawRadius = Mathf.Max(0, _drawRadius);
62 _drawResolution = Mathf.Clamp(_drawResolution, 3, 24);
63 _minSegmentLength = Mathf.Max(0, _minSegmentLength);
67 if (_pinchDetectors.Length == 0) {
68 Debug.LogWarning(
"No pinch detectors were specified! PinchDraw can not draw any lines without PinchDetectors.");
73 _drawStates =
new DrawState[_pinchDetectors.Length];
74 for (
int i = 0; i < _pinchDetectors.Length; i++) {
75 _drawStates[i] =
new DrawState(
this);
80 for (
int i = 0; i < _pinchDetectors.Length; i++) {
81 var detector = _pinchDetectors[i];
82 var drawState = _drawStates[i];
84 if (detector.DidStartHold) {
85 drawState.BeginNewLine();
88 if (detector.DidRelease) {
89 drawState.FinishLine();
92 if (detector.IsHolding) {
93 drawState.UpdateLine(detector.Position);
98 private class DrawState {
99 private List<Vector3> _vertices =
new List<Vector3>();
100 private List<int> _tris =
new List<int>();
101 private List<Vector2> _uvs =
new List<Vector2>();
102 private List<Color> _colors =
new List<Color>();
104 private PinchDraw _parent;
106 private int _rings = 0;
114 private SmoothedVector3 _smoothedPosition;
116 public DrawState(PinchDraw parent) {
119 _smoothedPosition =
new SmoothedVector3();
120 _smoothedPosition.delay = parent._smoothingDelay;
121 _smoothedPosition.reset =
true;
124 public GameObject BeginNewLine() {
131 _smoothedPosition.reset =
true;
134 _mesh.name =
"Line Mesh";
137 GameObject lineObj =
new GameObject(
"Line Object");
138 lineObj.transform.position =
Vector3.zero;
139 lineObj.transform.rotation =
Quaternion.identity;
140 lineObj.transform.localScale =
Vector3.one;
141 lineObj.AddComponent<MeshFilter>().mesh = _mesh;
142 lineObj.AddComponent<MeshRenderer>().sharedMaterial = _parent._material;
147 public void UpdateLine(Vector3 position) {
148 _smoothedPosition.Update(position, Time.deltaTime);
150 bool shouldAdd =
false;
152 shouldAdd |= _vertices.Count == 0;
153 shouldAdd |=
Vector3.Distance(_prevRing0, _smoothedPosition.value) >= _parent._minSegmentLength;
156 addRing(_smoothedPosition.value);
161 public void FinishLine() {
162 _mesh.UploadMeshData(
true);
165 private void updateMesh() {
166 _mesh.SetVertices(_vertices);
167 _mesh.SetColors(_colors);
168 _mesh.SetUVs(0, _uvs);
169 _mesh.SetIndices(_tris.ToArray(), MeshTopology.Triangles, 0);
170 _mesh.RecalculateBounds();
171 _mesh.RecalculateNormals();
174 private void addRing(Vector3 ringPosition) {
188 Vector3 direction = ringPosition - _prevRing0;
191 if (angleToUp < 10 || angleToUp > 170) {
197 ringNormal = ringNormal.normalized;
199 _prevNormal0 = ringNormal;
200 }
else if (_rings > 2) {
201 Vector3 prevPerp =
Vector3.Cross(_prevRing0 - _prevRing1, _prevNormal0);
202 ringNormal =
Vector3.Cross(prevPerp, ringPosition - _prevRing0).normalized;
208 ringPosition - _prevRing1,
214 updateRingVerts(_vertices.Count - _parent._drawResolution,
216 ringPosition - _prevRing0,
219 updateRingVerts(_vertices.Count - _parent._drawResolution * 2,
221 ringPosition - _prevRing0,
224 updateRingVerts(_vertices.Count - _parent._drawResolution * 3,
226 ringPosition - _prevRing1,
231 _prevRing1 = _prevRing0;
232 _prevRing0 = ringPosition;
234 _prevNormal0 = ringNormal;
237 private void addVertexRing() {
238 for (
int i = 0; i < _parent._drawResolution; i++) {
240 _uvs.Add(
new Vector2(i / (_parent._drawResolution - 1.0f), 0));
241 _colors.Add(_parent._drawColor);
246 private void addTriSegment() {
247 for (
int i = 0; i < _parent._drawResolution; i++) {
248 int i0 = _vertices.Count - 1 - i;
249 int i1 = _vertices.Count - 1 - ((i + 1) % _parent._drawResolution);
252 _tris.Add(i1 - _parent._drawResolution);
253 _tris.Add(i0 - _parent._drawResolution);
257 _tris.Add(i1 - _parent._drawResolution);
261 private void updateRingVerts(
int offset, Vector3 ringPosition, Vector3 direction, Vector3 normal,
float radiusScale) {
262 direction = direction.normalized;
263 normal = normal.normalized;
265 for (
int i = 0; i < _parent._drawResolution; i++) {
266 float angle = 360.0f * (i / (float)(_parent._drawResolution));
268 Vector3 ringSpoke = rotator * normal * _parent._drawRadius * radiusScale;
269 _vertices[offset + i] = ringPosition + ringSpoke;
A basic utility class to aid in creating pinch based actions. Once linked with a HandModelBase,...