262 lines
6.4 KiB
C#
262 lines
6.4 KiB
C#
|
|
using Godot;
|
|
using Rokojori;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Rokojori
|
|
{
|
|
public enum TubeSegmentMode
|
|
{
|
|
Fixed_Division,
|
|
Depending_On_Length,
|
|
Maximum_Of_Both,
|
|
Minimum_Of_Both
|
|
}
|
|
|
|
public enum ShapeOrientationMode
|
|
{
|
|
Auto,
|
|
Original,
|
|
Reverse
|
|
}
|
|
|
|
[Tool]
|
|
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Spline.svg") ]
|
|
public partial class Tube : Node3D
|
|
{
|
|
[Export]
|
|
public MeshInstance3D output;
|
|
|
|
[Export]
|
|
public Spline spline;
|
|
|
|
[Export]
|
|
public TubeSegmentMode segmentMode = TubeSegmentMode.Fixed_Division;
|
|
|
|
[Export]
|
|
public int fixedSplineSegmentDivisions = 20;
|
|
|
|
[Export]
|
|
public float splineSegmentLength = 2;
|
|
|
|
|
|
[Export]
|
|
public bool undistortSplineSegments = true;
|
|
|
|
[Export]
|
|
public Curve twistCurve;
|
|
|
|
[Export]
|
|
public float radius;
|
|
|
|
[Export]
|
|
public int radialSegments = 8;
|
|
|
|
[Export]
|
|
public Curve radiusSizeCurve;
|
|
|
|
[Export]
|
|
public Curve radiusWidthCurve;
|
|
|
|
[Export]
|
|
public Curve radiusHeightCurve;
|
|
|
|
[Export]
|
|
public bool scaleRadiusByPathTransforms = true;
|
|
|
|
[Export]
|
|
public TubeShape[] shapes;
|
|
|
|
[Export]
|
|
public bool update;
|
|
|
|
[Export]
|
|
public bool updateAlways;
|
|
|
|
|
|
#if TOOLS
|
|
|
|
public void DrawGizmo( EditorNode3DGizmoPlugin gizmoPlugin, EditorNode3DGizmo gizmo )
|
|
{
|
|
/*
|
|
ClearCurveCache();
|
|
|
|
var curve = GetCurve();
|
|
|
|
gizmo.Clear();
|
|
|
|
var linePoints = new List<Vector3>();
|
|
|
|
int resolution = editorResolution <= 0 ? 20 : editorResolution;
|
|
|
|
renderedResolution = editorResolution;
|
|
|
|
var lastPoint = ToLocal( curve.SampleAt( 0 ) );
|
|
|
|
for ( int i = 1; i < resolution; i++ )
|
|
{
|
|
var t = i / (float) (resolution - 1 );
|
|
var point = ToLocal( curve.SampleAt( t ) );
|
|
|
|
linePoints.Add( lastPoint );
|
|
linePoints.Add( point );
|
|
|
|
lastPoint = point;
|
|
}
|
|
|
|
for ( int i = 0; i < curve.points.Count; i++ )
|
|
{
|
|
var p = curve.points[ i ];
|
|
linePoints.Add( ToLocal( p.position ) );
|
|
linePoints.Add( ToLocal( p.tangentBefore.position ) );
|
|
|
|
linePoints.Add( ToLocal( p.position ) );
|
|
linePoints.Add( ToLocal( p.tangentNext.position ) );
|
|
}
|
|
|
|
var material = gizmoPlugin.GetMaterial( "main", gizmo );
|
|
|
|
gizmo.AddLines( linePoints.ToArray(), material, false );
|
|
|
|
*/
|
|
}
|
|
|
|
public override void _Process( double delta )
|
|
{
|
|
if ( ! ( updateAlways || update ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( spline == null )
|
|
{
|
|
return;
|
|
}
|
|
|
|
update = false;
|
|
|
|
|
|
var mg = CreateMesh();
|
|
output.Mesh = mg.GenerateMesh();
|
|
|
|
UpdateGizmos();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
MeshGeometry CreateMesh()
|
|
{
|
|
var curve = spline.GetCurve();
|
|
int splineSegments = fixedSplineSegmentDivisions;
|
|
|
|
if ( TubeSegmentMode.Fixed_Division != segmentMode )
|
|
{
|
|
splineSegments = Mathf.CeilToInt( curve.ComputeLength( curve.points.Count * 3 ) / splineSegmentLength );
|
|
|
|
if ( TubeSegmentMode.Maximum_Of_Both == segmentMode )
|
|
{
|
|
splineSegments = Mathf.Max( splineSegments, fixedSplineSegmentDivisions );
|
|
}
|
|
if ( TubeSegmentMode.Minimum_Of_Both == segmentMode )
|
|
{
|
|
splineSegments = Mathf.Min( splineSegments, fixedSplineSegmentDivisions );
|
|
}
|
|
}
|
|
|
|
var shapesList = new List<TubeShape>();
|
|
|
|
if ( shapes != null && shapes.Length > 0 )
|
|
{
|
|
shapesList.AddRange( shapes );
|
|
Lists.Sort( shapesList, s => s.tubePosition );
|
|
|
|
shapesList.ForEach( s => s.ClearCache() );
|
|
|
|
}
|
|
|
|
|
|
var mg = MeshGeometry.CreateFromUVFunction(
|
|
( Vector2 uv ) =>
|
|
{
|
|
var t = undistortSplineSegments ? curve.ComputeTforNormalizedCurveLength( uv.Y, splineSegments ) : uv.Y;
|
|
var index = curve.NormalizedToPointIndex( t );
|
|
var pose = curve.PoseAt( t );
|
|
var radiusSize = radius * ( radiusSizeCurve == null ? 1 : radiusSizeCurve.Sample( t ) );
|
|
var sizeX = radiusSize;
|
|
var sizeY = radiusSize;
|
|
var twistOffset = 0f;
|
|
|
|
if ( radiusWidthCurve != null )
|
|
{
|
|
sizeX *= radiusWidthCurve.Sample( t );
|
|
}
|
|
|
|
if ( radiusHeightCurve != null )
|
|
{
|
|
sizeY *= radiusHeightCurve.Sample( t );
|
|
}
|
|
|
|
if ( scaleRadiusByPathTransforms )
|
|
{
|
|
|
|
var splineScale = curve.SmoothStepScaleByPointIndex( index );
|
|
|
|
if ( scaleRadiusByPathTransforms )
|
|
{
|
|
sizeX *= splineScale.X;
|
|
sizeY *= splineScale.Y;
|
|
}
|
|
}
|
|
|
|
if ( twistCurve != null )
|
|
{
|
|
twistOffset = Mathf.DegToRad( twistCurve.Sample( t ) );
|
|
}
|
|
|
|
twistOffset += Mathf.DegToRad( curve.SmoothStepTwistByPointIndex( index ) * 360 );
|
|
|
|
var twistRotation = Math3D.RotateZ( twistOffset ).Normalized();
|
|
|
|
var scale = new Vector3( sizeX, sizeY, 0 );
|
|
|
|
if ( shapesList.Count > 0 )
|
|
{
|
|
if ( shapesList.Count == 1 )
|
|
{
|
|
return shapesList[ 0 ].GetPose( undistortSplineSegments, splineSegments, radialSegments, pose, uv, scale, twistRotation );
|
|
}
|
|
|
|
var lerpResult = Lists.LerpIndex( shapesList, uv.Y, s => s.tubePosition );
|
|
|
|
|
|
var closestShape = shapesList[ lerpResult.closestIndex ];
|
|
var secondShape = shapesList[ lerpResult.secondIndex ];
|
|
|
|
var closestPose = closestShape.GetPose( undistortSplineSegments, splineSegments, radialSegments, pose, uv, scale, twistRotation );
|
|
var secondPose = secondShape.GetPose( undistortSplineSegments, splineSegments, radialSegments, pose, uv, scale, twistRotation );
|
|
|
|
var smoothLerp = Mathf.SmoothStep( 0f, 1f, lerpResult.lerpAmount );
|
|
return Pose.Lerp( closestPose, secondPose, smoothLerp );
|
|
|
|
}
|
|
else
|
|
{
|
|
var angle = uv.X * 2f * Mathf.Pi * ( sizeX / sizeY );
|
|
var circlePose = Pose.Create( Vector3.Zero, pose.rotation * Math3D.RotateZ( angle ) );
|
|
var circleStart = Vector3.Up * radiusSize * scale;
|
|
|
|
var positionOnCircle = circlePose.Apply( circleStart );
|
|
|
|
return Pose.Create( positionOnCircle + pose.position, circlePose.rotation );
|
|
}
|
|
|
|
},
|
|
radialSegments, splineSegments
|
|
);
|
|
|
|
return mg;
|
|
}
|
|
|
|
}
|
|
} |