Initialer Upload neues Unity-Projekt

This commit is contained in:
Daniel Ocks
2025-07-21 09:11:14 +02:00
commit eeca72985b
14558 changed files with 1508140 additions and 0 deletions

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Assertions;
namespace Oculus.Interaction.DistanceReticles
{
public class DistantInteractionLineRendererVisual : DistantInteractionLineVisual
{
[SerializeField]
private LineRenderer _lineRenderer;
protected override void Start()
{
base.Start();
this.AssertField(_lineRenderer, nameof(_lineRenderer));
_lineRenderer.positionCount = NumLinePoints;
}
protected override void RenderLine(Vector3[] linePoints)
{
_lineRenderer.SetPositions(linePoints);
_lineRenderer.enabled = true;
}
protected override void HideLine()
{
_lineRenderer.enabled = false;
}
#region Inject
public void InjectAllDistantInteractionLineRendererVisual(IDistanceInteractor interactor,
LineRenderer lineRenderer)
{
InjectDistanceInteractor(interactor);
InjectLineRenderer(lineRenderer);
}
public void InjectLineRenderer(LineRenderer lineRenderer)
{
_lineRenderer = lineRenderer;
}
#endregion
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 49d2336476ec912499a3c0aff23be4e4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,228 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using UnityEngine;
namespace Oculus.Interaction.DistanceReticles
{
public abstract class DistantInteractionLineVisual : MonoBehaviour
{
[SerializeField, Interface(typeof(IDistanceInteractor))]
private UnityEngine.Object _distanceInteractor;
public IDistanceInteractor DistanceInteractor { get; protected set; }
[SerializeField]
private float _visualOffset = 0.07f;
public float VisualOffset
{
get
{
return _visualOffset;
}
set
{
_visualOffset = value;
}
}
private Vector3[] _linePoints;
[SerializeField]
private bool _visibleDuringNormal;
private IReticleData _target;
[SerializeField]
private int _numLinePoints = 20;
protected int NumLinePoints => _numLinePoints;
[SerializeField]
private float _targetlessLength = 0.5f;
protected float TargetlessLength => _targetlessLength;
protected bool _started;
private bool _shouldDrawLine;
private DummyPointReticle _dummyTarget = new DummyPointReticle();
private void Awake()
{
DistanceInteractor = _distanceInteractor as IDistanceInteractor;
}
protected virtual void Start()
{
this.BeginStart(ref _started);
this.AssertField(DistanceInteractor, nameof(DistanceInteractor));
_linePoints = new Vector3[NumLinePoints];
this.EndStart(ref _started);
}
protected virtual void OnEnable()
{
if (_started)
{
DistanceInteractor.WhenStateChanged += HandleStateChanged;
DistanceInteractor.WhenPostprocessed += HandlePostProcessed;
}
}
protected virtual void OnDisable()
{
if (_started)
{
DistanceInteractor.WhenStateChanged -= HandleStateChanged;
DistanceInteractor.WhenPostprocessed -= HandlePostProcessed;
}
}
private void HandleStateChanged(InteractorStateChangeArgs args)
{
switch (args.NewState)
{
case InteractorState.Normal:
if (args.PreviousState != InteractorState.Disabled)
{
InteractableUnset();
}
break;
case InteractorState.Hover:
if (args.PreviousState == InteractorState.Normal)
{
InteractableSet(DistanceInteractor.DistanceInteractable);
}
break;
}
if (args.NewState == InteractorState.Select
|| args.NewState == InteractorState.Disabled
|| args.PreviousState == InteractorState.Disabled)
{
_shouldDrawLine = false;
}
else if (args.NewState == InteractorState.Hover)
{
_shouldDrawLine = true;
}
else if (args.NewState == InteractorState.Normal)
{
_shouldDrawLine = _visibleDuringNormal;
}
}
private void HandlePostProcessed()
{
if (_shouldDrawLine)
{
UpdateLine();
}
else
{
HideLine();
}
}
protected virtual void InteractableSet(IRelativeToRef interactable)
{
Component component = interactable as Component;
if (component == null)
{
_target = null;
return;
}
if (!component.TryGetComponent(out _target))
{
_dummyTarget.Target = interactable.RelativeTo;
_target = _dummyTarget;
}
}
protected virtual void InteractableUnset()
{
_target = null;
}
private void UpdateLine()
{
Vector3 direction = DistanceInteractor.Origin.forward;
Vector3 origin = DistanceInteractor.Origin.position;
Vector3 start = origin + direction * VisualOffset;
Vector3 end = TargetHit(DistanceInteractor.HitPoint);
Vector3 middle = start + direction * Vector3.Distance(start, end) * 0.5f;
for (int i = 0; i < NumLinePoints; i++)
{
float t = i / (NumLinePoints - 1f);
Vector3 point = EvaluateBezier(start, middle, end, t);
_linePoints[i] = point;
}
RenderLine(_linePoints);
}
protected abstract void RenderLine(Vector3[] linePoints);
protected abstract void HideLine();
protected Vector3 TargetHit(Vector3 hitPoint)
{
if (_target != null)
{
return _target.ProcessHitPoint(hitPoint);
}
return DistanceInteractor.Origin.position
+ DistanceInteractor.Origin.forward * _targetlessLength;
}
protected static Vector3 EvaluateBezier(Vector3 start, Vector3 middle, Vector3 end, float t)
{
t = Mathf.Clamp01(t);
float oneMinusT = 1f - t;
return (oneMinusT * oneMinusT * start)
+ (2f * oneMinusT * t * middle)
+ (t * t * end);
}
private class DummyPointReticle : IReticleData
{
public Transform Target { get; set; }
public Vector3 ProcessHitPoint(Vector3 hitPoint)
{
return Target.position;
}
}
#region Inject
public void InjectAllDistantInteractionLineVisual(IDistanceInteractor interactor)
{
InjectDistanceInteractor(interactor);
}
public void InjectDistanceInteractor(IDistanceInteractor interactor)
{
_distanceInteractor = interactor as UnityEngine.Object;
DistanceInteractor = interactor;
}
#endregion
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 63dcf920b7ab4c74c816cf2144feb287
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,114 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Assertions;
namespace Oculus.Interaction.DistanceReticles
{
public class DistantInteractionPolylineVisual : DistantInteractionLineVisual
{
[SerializeField]
private Color _color = Color.white;
public Color Color
{
get
{
return _color;
}
set
{
_color = value;
}
}
[SerializeField]
private float _lineWidth = 0.02f;
public float LineWidth
{
get
{
return _lineWidth;
}
set
{
_lineWidth = value;
}
}
private List<Vector4> _linePointsVec4;
[SerializeField]
private Material _lineMaterial;
private PolylineRenderer _polylineRenderer;
protected override void Start()
{
base.Start();
this.AssertField(_lineMaterial, nameof(_lineMaterial));
_polylineRenderer = new PolylineRenderer(_lineMaterial);
_linePointsVec4 = new List<Vector4>(new Vector4[NumLinePoints]);
}
private void OnDestroy()
{
_polylineRenderer.Cleanup();
}
protected override void RenderLine(Vector3[] linePoints)
{
for (int i = 0; i < linePoints.Length; i++)
{
Vector3 p = linePoints[i];
_linePointsVec4[i] = new Vector4(p.x, p.y, p.z, _lineWidth);
}
_polylineRenderer.SetLines(_linePointsVec4, _color);
_polylineRenderer.RenderLines();
}
protected override void HideLine()
{
}
#region Inject
public void InjectAllDistantInteractionPolylineVisual(IDistanceInteractor interactor,
Color color, Material material)
{
InjectDistanceInteractor(interactor);
InjectLineColor(color);
InjectLineMaterial(material);
}
public void InjectLineColor(Color color)
{
_color = color;
}
public void InjectLineMaterial(Material material)
{
_lineMaterial = material;
}
#endregion
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ec4a79a4dec34914e91ea89f5cd85cdf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,84 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using UnityEngine;
using UnityEngine.Assertions;
namespace Oculus.Interaction.DistanceReticles
{
public class DistantInteractionTubeVisual : DistantInteractionLineVisual
{
[SerializeField]
private TubeRenderer _tubeRenderer;
private TubePoint[] _tubePoints;
protected override void Start()
{
base.Start();
Assert.IsNotNull(_tubeRenderer);
}
protected override void RenderLine(Vector3[] linePoints)
{
InitializeArcPoints(linePoints);
_tubeRenderer.RenderTube(_tubePoints, Space.World);
}
protected override void HideLine()
{
_tubeRenderer.Hide();
}
private void InitializeArcPoints(Vector3[] linePoints)
{
if (_tubePoints == null
|| _tubePoints.Length < linePoints.Length)
{
_tubePoints = new TubePoint[linePoints.Length];
}
float totalLength = 0f;
for (int i = 1; i < linePoints.Length; i++)
{
totalLength += (linePoints[i] - linePoints[i - 1]).magnitude;
}
for (int i = 0; i < linePoints.Length; i++)
{
Vector3 difference = i == 0 ? linePoints[i + 1] - linePoints[i]
: linePoints[i] - linePoints[i - 1];
_tubePoints[i].position = linePoints[i];
_tubePoints[i].rotation = Quaternion.LookRotation(difference);
_tubePoints[i].relativeLength = i == 0 ? 0f
: _tubePoints[i - 1].relativeLength + (difference.magnitude / totalLength);
}
}
#region Inject
public void InjectAllDistantInteractionPolylineVisual(IDistanceInteractor interactor)
{
InjectDistanceInteractor(interactor);
}
#endregion
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 50f211aff3d26554691f0499eaa219e5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using UnityEngine;
namespace Oculus.Interaction.DistanceReticles
{
public interface IReticleData
{
Vector3 ProcessHitPoint(Vector3 hitPoint);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 02f66d477a24d6846bb998939cfc493e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,138 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using UnityEngine;
namespace Oculus.Interaction.DistanceReticles
{
public abstract class InteractorReticle<TReticleData> : MonoBehaviour
where TReticleData : class, IReticleData
{
[SerializeField]
private bool _visibleDuringSelect = false;
private bool VisibleDuringSelect
{
get
{
return _visibleDuringSelect;
}
set
{
_visibleDuringSelect = value;
}
}
protected bool _started;
protected TReticleData _targetData;
private bool _drawn;
protected abstract IInteractorView Interactor { get; set; }
protected abstract Component InteractableComponent { get; }
protected virtual void Start()
{
this.BeginStart(ref _started);
this.AssertField(Interactor, nameof(Interactor));
Hide();
this.EndStart(ref _started);
}
protected virtual void OnEnable()
{
if (_started)
{
Interactor.WhenStateChanged += HandleStateChanged;
Interactor.WhenPostprocessed += HandlePostProcessed;
}
}
protected virtual void OnDisable()
{
if (_started)
{
Interactor.WhenStateChanged -= HandleStateChanged;
Interactor.WhenPostprocessed -= HandlePostProcessed;
}
}
private void HandleStateChanged(InteractorStateChangeArgs args)
{
if (args.NewState == InteractorState.Normal
|| args.NewState == InteractorState.Disabled)
{
InteractableUnset();
}
else if (args.NewState == InteractorState.Hover
&& args.PreviousState != InteractorState.Select)
{
InteractableSet(InteractableComponent);
}
}
private void HandlePostProcessed()
{
if (_targetData != null
&& (Interactor.State == InteractorState.Hover
|| (Interactor.State == InteractorState.Select && _visibleDuringSelect)))
{
if (!_drawn)
{
_drawn = true;
Draw(_targetData);
}
Align(_targetData);
}
else if (_drawn)
{
_drawn = false;
Hide();
}
}
private void InteractableSet(Component interactable)
{
if (interactable != null
&& interactable.TryGetComponent(out _targetData))
{
_drawn = false;
}
else
{
_targetData = null;
}
}
private void InteractableUnset()
{
if (_drawn)
{
_drawn = false;
Hide();
}
_targetData = default(TReticleData);
}
#region Drawing
protected abstract void Draw(TReticleData data);
protected abstract void Align(TReticleData data);
protected abstract void Hide();
#endregion
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e2bf09818682cd64fbb06b54214d446e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using UnityEngine;
namespace Oculus.Interaction.DistanceReticles
{
public class ReticleDataGhost : MonoBehaviour, IReticleData
{
[SerializeField, Optional]
private Transform _targetPoint;
public Vector3 ProcessHitPoint(Vector3 hitPoint)
{
return _targetPoint != null ? _targetPoint.position
: this.transform.position;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4fed8706ac2c0e44c8a0abc84a62a563
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using UnityEngine;
namespace Oculus.Interaction.DistanceReticles
{
public class ReticleDataIcon : MonoBehaviour, IReticleData
{
[SerializeField, Optional]
private MeshRenderer _renderer;
[SerializeField, Optional]
private Texture _customIcon;
public Texture CustomIcon
{
get
{
return _customIcon;
}
set
{
_customIcon = value;
}
}
[SerializeField]
[Range(0f, 1f)]
private float _snappiness;
public float Snappiness
{
get
{
return _snappiness;
}
set
{
_snappiness = value;
}
}
public Vector3 GetTargetSize()
{
if (_renderer != null)
{
return _renderer.bounds.size;
}
return this.transform.localScale;
}
public Vector3 ProcessHitPoint(Vector3 hitPoint)
{
return Vector3.Lerp(hitPoint, this.transform.position, _snappiness);
}
#region Inject
public void InjectOptionalRenderer(MeshRenderer renderer)
{
_renderer = renderer;
}
#endregion
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0529a9671a3b6a74fab00c4d05312c64
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using UnityEngine;
namespace Oculus.Interaction.DistanceReticles
{
public class ReticleDataMesh : MonoBehaviour, IReticleData
{
[SerializeField]
private MeshFilter _filter;
public MeshFilter Filter
{
get
{
return _filter;
}
set
{
_filter = value;
}
}
public Transform Target => _filter.transform;
public Vector3 ProcessHitPoint(Vector3 hitPoint)
{
return _filter.transform.position;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 830a777c9bbd60441b589b654b94b2c5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,189 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using Oculus.Interaction.Grab;
using Oculus.Interaction.HandGrab;
using Oculus.Interaction.Input;
using UnityEngine;
using UnityEngine.Serialization;
namespace Oculus.Interaction.DistanceReticles
{
public class ReticleGhostDrawer : InteractorReticle<ReticleDataGhost>
{
[FormerlySerializedAs("_handGrabber")]
[SerializeField, Interface(typeof(IHandGrabInteractor), typeof(IInteractorView))]
private UnityEngine.Object _handGrabInteractor;
private IHandGrabInteractor HandGrabInteractor { get; set; }
[FormerlySerializedAs("_modifier")]
[SerializeField]
private SyntheticHand _syntheticHand;
[SerializeField, Interface(typeof(IHandVisual))]
[FormerlySerializedAs("_visualHand")]
private UnityEngine.Object _handVisual;
private IHandVisual HandVisual;
private bool _areFingersFree = true;
private bool _isWristFree = true;
protected override IInteractorView Interactor { get; set; }
protected override Component InteractableComponent => HandGrabInteractor.TargetInteractable as Component;
private ITrackingToWorldTransformer Transformer;
protected virtual void Awake()
{
HandVisual = _handVisual as IHandVisual;
HandGrabInteractor = _handGrabInteractor as IHandGrabInteractor;
Interactor = _handGrabInteractor as IInteractorView;
}
protected override void Start()
{
this.BeginStart(ref _started, () => base.Start());
this.AssertField(HandGrabInteractor, nameof(_handGrabInteractor));
this.AssertField(Interactor, nameof(_handGrabInteractor));
this.AssertField(HandVisual, nameof(HandVisual));
this.AssertField(_syntheticHand, nameof(_syntheticHand));
Transformer = _syntheticHand.GetData().Config.TrackingToWorldTransformer;
Hide();
this.EndStart(ref _started);
}
private void UpdateHandPose(IHandGrabState snapper)
{
HandGrabTarget snap = snapper.HandGrabTarget;
if (snap == null)
{
FreeFingers();
FreeWrist();
return;
}
if (snap.HandPose != null)
{
UpdateFingers(snap.HandPose, snapper.GrabbingFingers());
_areFingersFree = false;
}
else
{
FreeFingers();
}
Pose wristLocalPose = snapper.GetVisualWristPose();
Pose wristPose = Transformer != null
? Transformer.ToTrackingPose(wristLocalPose)
: wristLocalPose;
_syntheticHand.LockWristPose(wristPose, 1f);
_isWristFree = false;
}
private void UpdateFingers(HandPose handPose, HandFingerFlags grabbingFingers)
{
Quaternion[] desiredRotations = handPose.JointRotations;
_syntheticHand.OverrideAllJoints(desiredRotations, 1f);
for (int fingerIndex = 0; fingerIndex < Constants.NUM_FINGERS; fingerIndex++)
{
int fingerFlag = 1 << fingerIndex;
JointFreedom fingerFreedom = handPose.FingersFreedom[fingerIndex];
if (fingerFreedom == JointFreedom.Constrained
&& ((int)grabbingFingers & fingerFlag) != 0)
{
fingerFreedom = JointFreedom.Locked;
}
_syntheticHand.SetFingerFreedom((HandFinger)fingerIndex, fingerFreedom);
}
}
private bool FreeFingers()
{
if (!_areFingersFree)
{
_syntheticHand.FreeAllJoints();
_areFingersFree = true;
return true;
}
return false;
}
private bool FreeWrist()
{
if (!_isWristFree)
{
_syntheticHand.FreeWrist();
_isWristFree = true;
return true;
}
return false;
}
protected override void Align(ReticleDataGhost data)
{
UpdateHandPose(HandGrabInteractor);
_syntheticHand.MarkInputDataRequiresUpdate();
}
protected override void Draw(ReticleDataGhost data)
{
HandVisual.ForceOffVisibility = false;
}
protected override void Hide()
{
HandVisual.ForceOffVisibility = true;
_syntheticHand.MarkInputDataRequiresUpdate();
}
#region Inject
public void InjectAllReticleGhostDrawer(IHandGrabInteractor handGrabInteractor,
SyntheticHand syntheticHand, IHandVisual visualHand)
{
InjectHandGrabInteractor(handGrabInteractor);
InjectSyntheticHand(syntheticHand);
InjectVisualHand(visualHand);
}
public void InjectHandGrabInteractor(IHandGrabInteractor handGrabInteractor)
{
_handGrabInteractor = handGrabInteractor as UnityEngine.Object;
HandGrabInteractor = handGrabInteractor;
Interactor = handGrabInteractor as IInteractorView;
}
public void InjectSyntheticHand(SyntheticHand syntheticHand)
{
_syntheticHand = syntheticHand;
}
public void InjectVisualHand(IHandVisual visualHand)
{
_handVisual = visualHand as UnityEngine.Object;
HandVisual = visualHand;
}
#endregion
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0c6aa09f2d128af4d93fb9fc29ecec33
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,164 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using UnityEngine;
using UnityEngine.Assertions;
namespace Oculus.Interaction.DistanceReticles
{
public class ReticleIconDrawer : InteractorReticle<ReticleDataIcon>
{
[SerializeField, Interface(typeof(IDistanceInteractor))]
private UnityEngine.Object _distanceInteractor;
private IDistanceInteractor DistanceInteractor { get; set; }
[SerializeField]
private MeshRenderer _renderer;
[SerializeField]
private Transform _centerEye;
[SerializeField]
private Texture _defaultIcon;
public Texture DefaultIcon
{
get
{
return _defaultIcon;
}
set
{
_defaultIcon = value;
}
}
[SerializeField]
private bool _constantScreenSize;
public bool ConstantScreenSize
{
get
{
return _constantScreenSize;
}
set
{
_constantScreenSize = value;
}
}
private Vector3 _originalScale;
protected override IInteractorView Interactor { get; set; }
protected override Component InteractableComponent => DistanceInteractor.DistanceInteractable as Component;
#region Editor events
protected virtual void OnValidate()
{
if (_renderer != null)
{
_renderer.sharedMaterial.mainTexture = _defaultIcon;
}
}
#endregion
protected virtual void Awake()
{
DistanceInteractor = _distanceInteractor as IDistanceInteractor;
Interactor = DistanceInteractor;
}
protected override void Start()
{
this.BeginStart(ref _started, () => base.Start());
this.AssertField(_renderer, nameof(_renderer));
this.AssertField(_centerEye, nameof(_centerEye));
_originalScale = this.transform.localScale;
this.EndStart(ref _started);
}
protected override void Draw(ReticleDataIcon dataIcon)
{
if (dataIcon != null
&& dataIcon.CustomIcon != null)
{
_renderer.material.mainTexture = dataIcon.CustomIcon;
}
else
{
_renderer.material.mainTexture = _defaultIcon;
}
if (!_constantScreenSize)
{
_renderer.transform.localScale = _originalScale * dataIcon.GetTargetSize().magnitude;
}
_renderer.enabled = true;
}
protected override void Align(ReticleDataIcon data)
{
this.transform.position = data.ProcessHitPoint(DistanceInteractor.HitPoint);
if (_renderer.enabled)
{
Vector3 dirToTarget = (_centerEye.position - transform.position).normalized;
transform.LookAt(transform.position - dirToTarget, Vector3.up);
if (_constantScreenSize)
{
float distance = Vector3.Distance(transform.position, _centerEye.position);
_renderer.transform.localScale = _originalScale * distance;
}
}
}
protected override void Hide()
{
_renderer.enabled = false;
}
#region Inject
public void InjectAllReticleIconDrawer(IDistanceInteractor distanceInteractor,
Transform centerEye, MeshRenderer renderer)
{
InjectDistanceInteractor(distanceInteractor);
InjectCenterEye(centerEye);
InjectRenderer(renderer);
}
public void InjectDistanceInteractor(IDistanceInteractor distanceInteractor)
{
_distanceInteractor = distanceInteractor as UnityEngine.Object;
DistanceInteractor = distanceInteractor;
Interactor = distanceInteractor;
}
public void InjectCenterEye(Transform centerEye)
{
_centerEye = centerEye;
}
public void InjectRenderer(MeshRenderer renderer)
{
_renderer = renderer;
}
#endregion
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f026be10edaad42429c52aa2200881dd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using Oculus.Interaction.HandGrab;
using UnityEngine;
using UnityEngine.Serialization;
namespace Oculus.Interaction.DistanceReticles
{
public class ReticleMeshDrawer : InteractorReticle<ReticleDataMesh>
{
[FormerlySerializedAs("_handGrabber")]
[SerializeField, Interface(typeof(IHandGrabInteractor), typeof(IInteractorView))]
private UnityEngine.Object _handGrabInteractor;
private IHandGrabInteractor HandGrabInteractor { get; set; }
[SerializeField]
private MeshFilter _filter;
[SerializeField]
private MeshRenderer _renderer;
[SerializeField]
private PoseTravelData _travelData = PoseTravelData.FAST;
public PoseTravelData TravelData
{
get
{
return _travelData;
}
set
{
_travelData = value;
}
}
protected override IInteractorView Interactor { get; set; }
protected override Component InteractableComponent => HandGrabInteractor.TargetInteractable as Component;
private Tween _tween;
protected virtual void Reset()
{
_filter = this.GetComponent<MeshFilter>();
_renderer = this.GetComponent<MeshRenderer>();
}
protected virtual void Awake()
{
HandGrabInteractor = _handGrabInteractor as IHandGrabInteractor;
Interactor = _handGrabInteractor as IInteractorView;
}
protected override void Start()
{
this.BeginStart(ref _started, () => base.Start());
this.AssertField(Interactor, nameof(_handGrabInteractor));
this.AssertField(HandGrabInteractor, nameof(_handGrabInteractor));
this.AssertField(_filter, nameof(_filter));
this.AssertField(_renderer, nameof(_renderer));
this.EndStart(ref _started);
}
protected override void Draw(ReticleDataMesh dataMesh)
{
_filter.sharedMesh = dataMesh.Filter.sharedMesh;
_filter.transform.localScale = dataMesh.Filter.transform.lossyScale;
_renderer.enabled = true;
Pose target = DestinationPose(dataMesh, HandGrabInteractor.GetTargetGrabPose());
_tween = _travelData.CreateTween(dataMesh.Target.GetPose(), target);
}
protected override void Hide()
{
_tween = null;
_renderer.enabled = false;
}
protected override void Align(ReticleDataMesh data)
{
Pose target = DestinationPose(data, HandGrabInteractor.GetTargetGrabPose());
_tween.UpdateTarget(target);
_tween.Tick();
_filter.transform.SetPose(_tween.Pose);
}
private Pose DestinationPose(ReticleDataMesh data, Pose worldSnapPose)
{
Pose targetOffset = PoseUtils.Delta(worldSnapPose, data.Target.GetPose());
HandGrabInteractor.HandGrabApi.Hand.GetRootPose(out Pose pose);
pose.Premultiply(HandGrabInteractor.WristToGrabPoseOffset);
pose.Premultiply(targetOffset);
return pose;
}
#region Inject
public void InjectAllReticleMeshDrawer(IHandGrabInteractor handGrabInteractor,
MeshFilter filter, MeshRenderer renderer)
{
InjectHandGrabInteractor(handGrabInteractor);
InjectFilter(filter);
InjectRenderer(renderer);
}
public void InjectHandGrabInteractor(IHandGrabInteractor handGrabInteractor)
{
_handGrabInteractor = handGrabInteractor as UnityEngine.Object;
HandGrabInteractor = handGrabInteractor;
Interactor = handGrabInteractor as IInteractorView;
}
public void InjectFilter(MeshFilter filter)
{
_filter = filter;
}
public void InjectRenderer(MeshRenderer renderer)
{
_renderer = renderer;
}
#endregion
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6d9d81be1c5cd1942a7572d99a4fca60
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,507 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Runtime.InteropServices;
using Unity.Collections;
using UnityEngine;
using UnityEngine.Rendering;
namespace Oculus.Interaction
{
public struct TubePoint
{
public Vector3 position;
public Quaternion rotation;
public float relativeLength;
}
/// <summary>
/// Creates and renders a tube mesh from sequence of points.
/// </summary>
public class TubeRenderer : MonoBehaviour
{
[StructLayout(LayoutKind.Sequential)]
private struct VertexLayout
{
public Vector3 pos;
public Color32 color;
public Vector2 uv;
}
[SerializeField]
private MeshFilter _filter;
[SerializeField]
private MeshRenderer _renderer;
[SerializeField]
private int _divisions = 6;
[SerializeField]
private int _bevel = 4;
[SerializeField]
private int _renderQueue = -1;
public int RenderQueue
{
get
{
return _renderQueue;
}
set
{
_renderQueue = value;
}
}
[SerializeField]
private Vector2 _renderOffset = Vector2.zero;
public Vector2 RenderOffset
{
get
{
return _renderOffset;
}
set
{
_renderOffset = value;
}
}
[SerializeField]
private float _radius = 0.005f;
public float Radius
{
get
{
return _radius;
}
set
{
_radius = value;
}
}
[SerializeField]
private Gradient _gradient;
public Gradient Gradient
{
get
{
return _gradient;
}
set
{
_gradient = value;
}
}
[SerializeField]
private Color _tint = Color.white;
public Color Tint
{
get
{
return _tint;
}
set
{
_tint = value;
}
}
[SerializeField, Range(0f, 1f)]
private float _progressFade = 0.2f;
public float ProgressFade
{
get
{
return _progressFade;
}
set
{
_progressFade = value;
}
}
[SerializeField]
private float _startFadeThresold = 0.2f;
public float StartFadeThresold
{
get
{
return _startFadeThresold;
}
set
{
_startFadeThresold = value;
}
}
[SerializeField]
private float _endFadeThresold = 0.2f;
public float EndFadeThresold
{
get
{
return _endFadeThresold;
}
set
{
_endFadeThresold = value;
}
}
[SerializeField]
private bool _invertThreshold = false;
public bool InvertThreshold
{
get
{
return _invertThreshold;
}
set
{
_invertThreshold = value;
}
}
[SerializeField]
private float _feather = 0.2f;
public float Feather
{
get
{
return _feather;
}
set
{
_feather = value;
}
}
[SerializeField]
private bool _mirrorTexture;
public bool MirrorTexture
{
get
{
return _mirrorTexture;
}
set
{
_mirrorTexture = value;
}
}
public float Progress { get; set; } = 0f;
public float TotalLength => _totalLength;
private VertexAttributeDescriptor[] _dataLayout;
private NativeArray<VertexLayout> _vertsData;
private VertexLayout _layout = new VertexLayout();
private Mesh _mesh;
private int[] _tris;
private int _initializedSteps = -1;
private int _vertsCount;
private float _totalLength = 0f;
private static readonly int _fadeLimitsShaderID = Shader.PropertyToID("_FadeLimit");
private static readonly int _fadeSignShaderID = Shader.PropertyToID("_FadeSign");
private static readonly int _offsetFactorShaderPropertyID = Shader.PropertyToID("_OffsetFactor");
private static readonly int _offsetUnitsShaderPropertyID = Shader.PropertyToID("_OffsetUnits");
#region Editor events
protected virtual void Reset()
{
_filter = this.GetComponent<MeshFilter>();
_renderer = this.GetComponent<MeshRenderer>();
}
#endregion
protected virtual void OnEnable()
{
_renderer.enabled = true;
}
protected virtual void OnDisable()
{
_renderer.enabled = false;
}
/// <summary>
/// Updates the mesh data for the tube with the specified points
/// </summary>
/// <param name="points">The points that the tube must follow</param>
/// <param name="space">Indicates if the points are specified in local space or world space</param>
public void RenderTube(TubePoint[] points, Space space = Space.Self)
{
int steps = points.Length;
if (steps != _initializedSteps)
{
InitializeMeshData(steps);
_initializedSteps = steps;
}
_vertsData = new NativeArray<VertexLayout>(_vertsCount, Allocator.Temp);
UpdateMeshData(points, space);
_renderer.enabled = enabled;
}
/// <summary>
/// Hides the renderer of the tube
/// </summary>
public void Hide()
{
_renderer.enabled = false;
}
private void InitializeMeshData(int steps)
{
_dataLayout = new VertexAttributeDescriptor[]
{
new VertexAttributeDescriptor(VertexAttribute.Position, VertexAttributeFormat.Float32, 3),
new VertexAttributeDescriptor(VertexAttribute.Color, VertexAttributeFormat.UNorm8, 4),
new VertexAttributeDescriptor(VertexAttribute.TexCoord0, VertexAttributeFormat.Float32, 2),
};
_vertsCount = SetVertexCount(steps, _divisions, _bevel);
SubMeshDescriptor submeshDesc = new SubMeshDescriptor(0, _tris.Length, MeshTopology.Triangles);
_mesh = new Mesh();
_mesh.SetVertexBufferParams(_vertsCount, _dataLayout);
_mesh.SetIndexBufferParams(_tris.Length, IndexFormat.UInt32);
_mesh.SetIndexBufferData(_tris, 0, 0, _tris.Length);
_mesh.subMeshCount = 1;
_mesh.SetSubMesh(0, submeshDesc);
_filter.mesh = _mesh;
}
private void UpdateMeshData(TubePoint[] points, Space space)
{
int steps = points.Length;
float totalLength = 0f;
Vector3 prevPoint = Vector3.zero;
Pose pose = Pose.identity;
Pose start = Pose.identity;
Pose end = Pose.identity;
Pose rootPose = this.transform.GetPose(Space.World);
Quaternion inverseRootRotation = Quaternion.Inverse(rootPose.rotation);
Vector3 rootPositionScaled = new Vector3(
rootPose.position.x / this.transform.lossyScale.x,
rootPose.position.y / this.transform.lossyScale.y,
rootPose.position.z / this.transform.lossyScale.z);
float uniformScale = space == Space.World ? this.transform.lossyScale.x : 1f;
TransformPose(points[0], ref start);
TransformPose(points[points.Length - 1], ref end);
BevelCap(start, false, 0);
for (int i = 0; i < steps; i++)
{
TransformPose(points[i], ref pose);
Vector3 point = pose.position;
Quaternion rotation = pose.rotation;
float progress = points[i].relativeLength;
Color color = Gradient.Evaluate(progress) * _tint;
if (i > 0)
{
totalLength += Vector3.Distance(point, prevPoint);
}
prevPoint = point;
if (i / (steps - 1f) < Progress)
{
color.a *= ProgressFade;
}
_layout.color = color;
WriteCircle(point, rotation, _radius, i + _bevel, progress);
}
BevelCap(end, true, _bevel + steps);
_mesh.bounds = new Bounds(
(start.position + end.position) * 0.5f,
end.position - start.position);
_mesh.SetVertexBufferData(_vertsData, 0, 0, _vertsData.Length, 0, MeshUpdateFlags.DontRecalculateBounds);
_totalLength = totalLength * uniformScale;
RedrawFadeThresholds();
void TransformPose(in TubePoint tubePoint, ref Pose pose)
{
if (space == Space.Self)
{
pose.position = tubePoint.position;
pose.rotation = tubePoint.rotation;
return;
}
pose.position = inverseRootRotation * (tubePoint.position - rootPositionScaled);
pose.rotation = inverseRootRotation * tubePoint.rotation;
}
}
/// <summary>
/// Resubmits the fading thresholds data to the material without re-generating the mesh
/// </summary>
public void RedrawFadeThresholds()
{
float originFadeIn = StartFadeThresold / _totalLength;
float originFadeOut = (StartFadeThresold + Feather) / _totalLength;
float endFadeIn = (_totalLength - EndFadeThresold) / _totalLength;
float endFadeOut = (_totalLength - EndFadeThresold - Feather) / _totalLength;
_renderer.material.SetVector(_fadeLimitsShaderID, new Vector4(
_invertThreshold ? originFadeOut : originFadeIn,
_invertThreshold ? originFadeIn : originFadeOut,
endFadeOut,
endFadeIn));
_renderer.material.SetFloat(_fadeSignShaderID, _invertThreshold ? -1 : 1);
_renderer.material.renderQueue = _renderQueue;
_renderer.material.SetFloat(_offsetFactorShaderPropertyID, _renderOffset.x);
_renderer.material.SetFloat(_offsetUnitsShaderPropertyID, _renderOffset.y);
}
private void BevelCap(in Pose pose, bool end, int indexOffset)
{
Vector3 origin = pose.position;
Quaternion rotation = pose.rotation;
for (int i = 0; i < _bevel; i++)
{
float radiusFactor = Mathf.InverseLerp(-1, _bevel + 1, i);
if (end)
{
radiusFactor = 1 - radiusFactor;
}
float positionFactor = Mathf.Sqrt(1 - radiusFactor * radiusFactor);
Vector3 point = origin + (end ? 1 : -1) * (rotation * Vector3.forward) * _radius * positionFactor;
WriteCircle(point, rotation, _radius * radiusFactor, i + indexOffset, end ? 1 : 0);
}
}
private void WriteCircle(Vector3 point, Quaternion rotation, float width, int index, float progress)
{
Color color = Gradient.Evaluate(progress) * _tint;
if (progress < Progress)
{
color.a *= ProgressFade;
}
_layout.color = color;
for (int j = 0; j <= _divisions; j++)
{
float radius = 2 * Mathf.PI * j / _divisions;
Vector3 circle = new Vector3(Mathf.Sin(radius), Mathf.Cos(radius), 0);
Vector3 normal = rotation * circle;
_layout.pos = point + normal * width;
if (_mirrorTexture)
{
float x = (j / (float)_divisions) * 2f;
if (j >= _divisions * 0.5f)
{
x = 2 - x;
}
_layout.uv = new Vector2(x, progress);
}
else
{
_layout.uv = new Vector2(j / (float)_divisions, progress);
}
int vertIndex = index * (_divisions + 1) + j;
_vertsData[vertIndex] = _layout;
}
}
private int SetVertexCount(int positionCount, int divisions, int bevelCap)
{
bevelCap = bevelCap * 2;
int vertsPerPosition = divisions + 1;
int vertCount = (positionCount + bevelCap) * vertsPerPosition;
int tubeTriangles = (positionCount - 1 + bevelCap) * divisions * 6;
int capTriangles = (divisions - 2) * 3;
int triangleCount = tubeTriangles + capTriangles * 2;
_tris = new int[triangleCount];
// handle triangulation
for (int i = 0; i < positionCount - 1 + bevelCap; i++)
{
// add faces
for (int j = 0; j < divisions; j++)
{
int vert0 = i * vertsPerPosition + j;
int vert1 = (i + 1) * vertsPerPosition + j;
int t = (i * divisions + j) * 6;
_tris[t] = vert0;
_tris[t + 1] = _tris[t + 4] = vert1;
_tris[t + 2] = _tris[t + 3] = vert0 + 1;
_tris[t + 5] = vert1 + 1;
}
}
// triangulate the ends
Cap(tubeTriangles, 0, divisions - 1, true);
Cap(tubeTriangles + capTriangles, vertCount - divisions, vertCount - 1);
void Cap(int t, int firstVert, int lastVert, bool clockwise = false)
{
for (int i = firstVert + 1; i < lastVert; i++)
{
_tris[t++] = firstVert;
_tris[t++] = clockwise ? i : i + 1;
_tris[t++] = clockwise ? i + 1 : i;
}
}
return vertCount;
}
#region Inject
public void InjectAllTubeRenderer(MeshFilter filter,
MeshRenderer renderer, int divisions, int bevel)
{
InjectFilter(filter);
InjectRenderer(renderer);
InjectDivisions(divisions);
InjectBevel(bevel);
}
public void InjectFilter(MeshFilter filter)
{
_filter = filter;
}
public void InjectRenderer(MeshRenderer renderer)
{
_renderer = renderer;
}
public void InjectDivisions(int divisions)
{
_divisions = divisions;
}
public void InjectBevel(int bevel)
{
_bevel = bevel;
}
#endregion
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 038d627f7b72e904382b2b0f8fb30c29
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: