rj-action-library/Runtime/Procedural/Scatter/Generators/GenerateFence.cs

138 lines
3.3 KiB
C#

using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class GenerateFence:GeneratorScatterer
{
[Export]
public Spline spline;
[Export]
public bool xzOnly = true;
[Export]
public float sampleDensity = 1;
[Export]
public GeneratorEntry segment;
[Export]
public float segmentLength;
[Export]
public Vector3 segmentRotation;
[Export]
public float segmentYOffset;
[Export]
public Vector3 scaleAxis = new Vector3( 1, 0, 0 );
[Export]
public GeneratorEntry pole;
[Export]
public float poleLength;
[Export]
public GeneratorEntry startPole;
[Export]
public float startPoleLength;
[Export]
public GeneratorEntry endPole;
[Export]
public float endPoleLength;
SplineCurve last;
LerpCurve3 equalSpacedCurve;
protected override List<ScatterPoint> _Scatter( List<ScatterPoint> points, Scatterer root )
{
CreateWeights();
var curve = spline.GetCurve();
if ( last != curve )
{
last = curve;
equalSpacedCurve = LerpCurve3.SampledEqually( curve, sampleDensity );
}
var curveLength = equalSpacedCurve.ComputeLength( 0 );
var numPoints = Mathf.CeilToInt( curveLength * sampleDensity );
var id = 0;
var positions = new List<Vector3>();
var rotations = new List<Quaternion>();
for ( int i = 0; i < numPoints; i++ )
{
var t = i / (float) ( numPoints - 1 );
var position = equalSpacedCurve.PositionAt( t );
var rawDirection = equalSpacedCurve.TangentAt( t, 1f / 100f );
var direction = rawDirection;
var length = direction.Length();
if ( length != 0 )
{
direction /= length;
}
/*RJLog.Log( "i:", i, "t:", t,
"P:", position,
"L:", length,
"RD:", rawDirection,
"D:", direction
);*/
var point = CreatePoint( points, id, position.X, position.Y, position.Z, pole );
point.rotation = Math3D.LookRotation( direction, Vector3.Up );
positions.Add( position );
rotations.Add( point.rotation );
id = point.creatorID + 1;
}
for ( int i = 0; i < positions.Count - 1; i++ )
{
var position = positions[ i ].Lerp( positions[ i + 1 ], 0.5f );
var direction = positions[ i + 1 ] - positions[ i ];
var rotation = Math3D.LookRotation( direction, Vector3.Up );
var length = direction.Length() / segmentLength - 1.0f;
var point = CreatePoint( points, id, position.X, position.Y + segmentYOffset, position.Z, segment );
point.rotation = rotation * Quaternion.FromEuler( segmentRotation / 180.0f * Mathf.Pi );
point.scale = Vector3.One + length * scaleAxis;
id = point.creatorID + 1;
}
return points;
}
ScatterPoint CreatePoint( List<ScatterPoint> points, int id, float x, float y, float z, GeneratorEntry entry )
{
var p = new ScatterPoint( this, id );
p.position = new Vector3( x, y, z );
p.visible = ! setDiscarded;
p.seed = Noise.CreateSeed( p.position );
p.scene = entry.GetPackedScene();
p.parent = entry.container;
points.Add( p );
return p;
}
}
}