192 lines
4.1 KiB
C#
192 lines
4.1 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using Godot;
|
|
using System;
|
|
|
|
|
|
|
|
namespace Rokojori
|
|
{
|
|
[Tool]
|
|
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Spline.svg") ]
|
|
public partial class LeafMesh:Node3D
|
|
{
|
|
[Export]
|
|
public MeshInstance3D output;
|
|
|
|
[Export]
|
|
public int seed;
|
|
|
|
[Export]
|
|
public bool update;
|
|
|
|
[Export]
|
|
public bool updateAlways;
|
|
|
|
[Export]
|
|
public float height;
|
|
|
|
[Export]
|
|
public Curve centerStrandShape;
|
|
|
|
[Export]
|
|
public float centerStrandShapeTopOffset;
|
|
|
|
[Export]
|
|
public float centerStrandShapeBottomOffset;
|
|
|
|
[Export]
|
|
public int numStrands;
|
|
|
|
[Export]
|
|
public Curve strandHeightPositions;
|
|
|
|
[Export]
|
|
public Curve strandShape;
|
|
|
|
[Export]
|
|
public Curve strandSize;
|
|
|
|
[Export]
|
|
public Curve strandWidth;
|
|
|
|
[Export]
|
|
public Curve strandLength;
|
|
|
|
[Export]
|
|
public Curve strandAngles;
|
|
|
|
[Export]
|
|
public int strandResolution = 20;
|
|
|
|
[Export]
|
|
public float positionJitterMax;
|
|
|
|
[Export]
|
|
public Vector2 positionJitterScale;
|
|
|
|
[Export]
|
|
public Vector2 positionJitterOffset;
|
|
|
|
|
|
|
|
public override void _Process( double delta )
|
|
{
|
|
if ( ! ( update || updateAlways ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
update = false;
|
|
|
|
try
|
|
{
|
|
Create();
|
|
}
|
|
catch ( System.Exception e )
|
|
{
|
|
RJLog.Error( e );
|
|
updateAlways = false;
|
|
}
|
|
}
|
|
|
|
void Create()
|
|
{
|
|
var paths = new List<Path2>();
|
|
|
|
for ( int i = 0; i < numStrands; i++ )
|
|
{
|
|
var part = CreateStrandPart( i );
|
|
|
|
var t = i / (float) ( numStrands - 1 );
|
|
var ht = strandHeightPositions.Sample( t );
|
|
var y = ht * height;
|
|
|
|
var turns = strandAngles.Sample( t );
|
|
var rotation = Mathf.DegToRad( turns * 360f );
|
|
|
|
var trsf = new Transform2D( rotation, new Vector2( 0, y ) );
|
|
|
|
part.ApplyTransform( trsf );
|
|
|
|
paths.Add( part );
|
|
|
|
var mirrored = part.Clone();
|
|
mirrored.MirrorX();
|
|
|
|
paths.Add( mirrored );
|
|
}
|
|
|
|
var centerPathPoints = new List<Vector2>();
|
|
|
|
for ( int i = 0; i < strandResolution; i++ )
|
|
{
|
|
var t = i / (float)( strandResolution - 1 );
|
|
var y = strandHeightPositions.Sample( t );
|
|
var x = centerStrandShape.Sample( t );
|
|
|
|
var size = ( height + centerStrandShapeTopOffset + centerStrandShapeBottomOffset );
|
|
var p = new Vector2( x, y * size - centerStrandShapeBottomOffset );
|
|
|
|
centerPathPoints.Add( p );
|
|
}
|
|
|
|
for ( int i = 0; i < strandResolution; i++ )
|
|
{
|
|
var index = ( strandResolution - 1 ) - i;
|
|
|
|
var p = centerPathPoints[ index ];
|
|
p.X = -p.X;
|
|
centerPathPoints.Add( p );
|
|
}
|
|
|
|
|
|
var centerPath = new Path2( centerPathPoints );
|
|
paths.Add( centerPath );
|
|
|
|
var random = new LCG();
|
|
random.SetSeed( seed );
|
|
paths.ForEach( p => p.PositionJitter( positionJitterMax, positionJitterScale, positionJitterOffset, random ) );
|
|
|
|
var shape = Shape2.UnionAll( paths );
|
|
|
|
// RJLog.Log( shape.ToSVGPath() );
|
|
|
|
|
|
var fillGeometry = shape.CreateFillMeshGeometry();
|
|
var mesh = fillGeometry.GenerateMesh();
|
|
// RJLog.Log( "First Path:", shape.paths[ 0 ].points, shape.paths, "mesh", fillGeometry.indices.Count );
|
|
output.Mesh = mesh;
|
|
|
|
}
|
|
|
|
Path2 CreateStrandPart( int index )
|
|
{
|
|
var points = new List<Vector2>();
|
|
var u = index / (float)( numStrands - 1 );
|
|
var s = strandSize.Sample( u );
|
|
var l = strandLength.Sample( u ) * s;
|
|
var w = strandWidth.Sample( u ) * s;
|
|
|
|
for ( int i = 0; i < strandResolution; i++ )
|
|
{
|
|
var t = i / (float)( strandResolution - 1 );
|
|
var p = new Vector2( t * l, strandShape.Sample( t ) * w );
|
|
|
|
points.Add( p );
|
|
}
|
|
|
|
for ( int i = 0; i < strandResolution; i++ )
|
|
{
|
|
var reverseIndex = ( strandResolution - 1 ) - i;
|
|
var lowerPoint = points[ reverseIndex ];
|
|
lowerPoint.Y = -lowerPoint.Y;
|
|
points.Add( lowerPoint );
|
|
}
|
|
|
|
var path = new Path2( points );
|
|
return path;
|
|
}
|
|
|
|
}
|
|
} |