121 lines
2.9 KiB
C#
121 lines
2.9 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using Godot;
|
|
using System;
|
|
|
|
|
|
|
|
namespace Rokojori
|
|
{
|
|
[Tool]
|
|
[GlobalClass]
|
|
public partial class ProjectOnColliders:Scatterer
|
|
{
|
|
|
|
|
|
|
|
[ExportGroup("Ray")]
|
|
[Export]
|
|
public Vector3 rayDirection = Vector3.Down;
|
|
|
|
[Export]
|
|
public float rayLength = 10;
|
|
|
|
[Export]
|
|
public Vector3 rayOffset = Vector3.Zero;
|
|
|
|
[ExportGroup("Normal")]
|
|
[Export(PropertyHint.Range, "0,1")]
|
|
public float rotationAlignment = 1;
|
|
|
|
[Export]
|
|
public bool discardSteepNormals = true;
|
|
|
|
[Export]
|
|
public Vector3 steepNormalDirection = Vector3.Down;
|
|
|
|
[Export(PropertyHint.Range, "0,180")]
|
|
public float steepNormalRemovalAngle = 0;
|
|
|
|
[ExportGroup("Collisions")]
|
|
[Export( PropertyHint.Layers3DPhysics)]
|
|
public uint collisionLayer = 0;
|
|
|
|
[Export]
|
|
public bool collideWithAreas = true;
|
|
|
|
[Export]
|
|
public bool collideWithBodies = true;
|
|
|
|
[Export]
|
|
public bool hitFromInside = true;
|
|
|
|
[Export]
|
|
public bool hitBackFaces = true;
|
|
|
|
protected override List<ScatterPoint> _Scatter( List<ScatterPoint> points )
|
|
{
|
|
var world = GetWorld3D();
|
|
var ray = new PhysicsRayQueryParameters3D();
|
|
var direction = rayDirection.Normalized();
|
|
var normalizedSteepNormalDirection = steepNormalDirection.Normalized();
|
|
|
|
var steepNormalRemovalTreshold = Mathf.Cos( Mathf.DegToRad( steepNormalRemovalAngle ) );
|
|
|
|
points.ForEach(
|
|
p =>
|
|
{
|
|
if ( ! p.visible )
|
|
{
|
|
return;
|
|
}
|
|
|
|
ray.From = p.globalPosition;
|
|
ray.To = ray.From + direction * rayLength;
|
|
|
|
var collisionData = CollisionData.FindCollision( world, ray,
|
|
( cd ) =>
|
|
{
|
|
if ( ! CollisionData.HasCollisionLayer( cd.collider ) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var colliderCollisionLayer = CollisionData.GetCollisionLayer( cd.collider );
|
|
var collides = ( colliderCollisionLayer & collisionLayer ) != 0;
|
|
// RJLog.Log( "Collision With:", "collides", collides, "colliderLayer:", colliderCollisionLayer, "own", collisionLayer, "name:", cd.collider.Name );
|
|
return collides;
|
|
|
|
}
|
|
);
|
|
|
|
p.visible = collisionData != null;
|
|
|
|
if ( ! p.visible )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( discardSteepNormals )
|
|
{
|
|
var dot = normalizedSteepNormalDirection.Dot( collisionData.normal );
|
|
|
|
if ( dot >= steepNormalRemovalTreshold )
|
|
{
|
|
p.visible = false;
|
|
return;
|
|
}
|
|
}
|
|
|
|
p.position = collisionData.position;
|
|
var alginedRotation =Math3D.AlignUp( p.rotation, collisionData.normal );
|
|
p.rotation = p.rotation.Slerp( alginedRotation, rotationAlignment );
|
|
|
|
}
|
|
|
|
);
|
|
|
|
return points;
|
|
}
|
|
}
|
|
} |