338 lines
6.4 KiB
C#
338 lines
6.4 KiB
C#
|
|
using Godot;
|
|
using Rokojori;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Rokojori
|
|
{
|
|
[Tool]
|
|
[GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Spline.svg") ]
|
|
public partial class Cuboid : Node3D
|
|
{
|
|
[Export]
|
|
public float size = 1;
|
|
|
|
[Export]
|
|
public float widthExtension = 0;
|
|
|
|
[Export]
|
|
public float heightExtension = 0;
|
|
|
|
[Export]
|
|
public float depthExtension = 0;
|
|
|
|
[Export]
|
|
public float borderSize = 0.1f;
|
|
|
|
[Export]
|
|
public MeshInstance3D output;
|
|
|
|
[Export]
|
|
public bool update = false;
|
|
|
|
[Export]
|
|
public bool updateAlways = false;
|
|
|
|
public override void _Process( double delta )
|
|
{
|
|
if ( ! ( update || updateAlways ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
update = false;
|
|
|
|
Create();
|
|
}
|
|
|
|
|
|
public float X()
|
|
{
|
|
return size + widthExtension;
|
|
}
|
|
|
|
public float Y()
|
|
{
|
|
return size + heightExtension;
|
|
}
|
|
|
|
public float Z()
|
|
{
|
|
return size + depthExtension;
|
|
}
|
|
|
|
MeshGeometry mg = null;
|
|
|
|
public void Create()
|
|
{
|
|
var maxBorderSize = ( MathX.Min( widthExtension, heightExtension, depthExtension ) + size ) / 2f;
|
|
borderSize = Mathf.Clamp( borderSize, 0, maxBorderSize );
|
|
mg = new MeshGeometry();
|
|
|
|
for ( int i = 0; i < 24; i++ )
|
|
{
|
|
var p = GetPointAt( i );
|
|
mg.vertices.Add( p );
|
|
|
|
if ( i < 4 )
|
|
{
|
|
mg.normals.Add( Vector3.Up );
|
|
}
|
|
else if ( i < 12 )
|
|
{
|
|
var cornerIndex = i - 4;
|
|
mg.normals.Add( GetEdgeNormal( cornerIndex ) );
|
|
}
|
|
else if ( i < 20 )
|
|
{
|
|
var cornerIndex = i - 12;
|
|
mg.normals.Add( GetEdgeNormal( cornerIndex ) );
|
|
}
|
|
else
|
|
{
|
|
mg.normals.Add( Vector3.Down );
|
|
}
|
|
|
|
|
|
mg.uvs.Add( Vector2.Zero );
|
|
}
|
|
|
|
mg.AddQuad( 0, 1, 2, 3 );
|
|
|
|
// back
|
|
AddSide( 2, 1 );
|
|
// right
|
|
AddSide( 7, 3 );
|
|
// left
|
|
AddSide( 0, 4 );
|
|
//front
|
|
AddSide( 5, 6 );
|
|
|
|
|
|
// side b,r
|
|
AddSide( 3, 2 );
|
|
// side f, r
|
|
AddSide( 6, 7 );
|
|
// side f, l
|
|
AddSide( 4, 5 );
|
|
// side b, l
|
|
AddSide( 1, 0 );
|
|
|
|
|
|
// left, back
|
|
AddCorner( 0, 1, 0 );
|
|
|
|
// back, right
|
|
AddCorner( 2, 3, 1 );
|
|
|
|
// left, front
|
|
AddCorner( 5, 4, 2 );
|
|
|
|
// front, right
|
|
AddCorner( 7, 6, 3 );
|
|
|
|
|
|
// back
|
|
AddFaceSide( 0, 1, 2, 1 );
|
|
|
|
// right
|
|
AddFaceSide( 1, 3, 7, 3 );
|
|
|
|
// front
|
|
AddFaceSide( 3, 2, 5, 6 );
|
|
|
|
// left
|
|
AddFaceSide( 2, 0, 0, 4 );
|
|
|
|
|
|
|
|
mg.AddQuad( 20, 21, 22, 23, true );
|
|
|
|
output.Mesh = mg.GenerateMesh();
|
|
|
|
}
|
|
|
|
void AddSide( int a, int b )
|
|
{
|
|
mg.AddQuad( te( a ), te( b ), be( a ), be( b ) );
|
|
}
|
|
|
|
void AddFaceSide( int fA, int fB, int eA, int eB )
|
|
{
|
|
mg.AddQuad( tf( fB ), tf( fA), te( eA ), te( eB ) );
|
|
mg.AddQuad( bf( fB ), bf( fA), be( eA ), be( eB ), true );
|
|
}
|
|
|
|
void AddCorner( int eA, int eB, int f )
|
|
{
|
|
mg.AddTriangle( te( eA ), te( eB ), tf( f ), true );
|
|
mg.AddTriangle( be( eA ), be( eB ), bf( f ) );
|
|
}
|
|
|
|
int tf( int index )
|
|
{
|
|
return index;
|
|
}
|
|
|
|
int te( int index )
|
|
{
|
|
return index + 4;
|
|
}
|
|
|
|
int be( int index )
|
|
{
|
|
return index + 12;
|
|
}
|
|
|
|
int bf( int index )
|
|
{
|
|
return index + 20;
|
|
}
|
|
|
|
|
|
public Vector3 GetEdgeNormal( int index )
|
|
{
|
|
switch ( index )
|
|
{
|
|
case 1: case 2: return Vector3.Back;
|
|
case 3: case 7: return Vector3.Right;
|
|
case 0: case 4: return Vector3.Left;
|
|
case 5: case 6: return Vector3.Forward;
|
|
}
|
|
|
|
return Vector3.Zero;
|
|
}
|
|
|
|
public Vector3 GetOffsetFor( int left, int front )
|
|
{
|
|
var x = borderSize * Mathf.Sign( left );
|
|
var z = borderSize * Mathf.Sign( front );
|
|
|
|
return new Vector3( x, 0, z );
|
|
}
|
|
|
|
public Vector3 GetBoundingCornerAt( int index, bool top )
|
|
{
|
|
// -Z
|
|
// 0 1
|
|
// *----*
|
|
//-X | | +X
|
|
// *----*
|
|
// 2 3
|
|
// +Z
|
|
|
|
var y = Y() / ( top ? 2 : -2 );
|
|
|
|
if ( 0 == index )
|
|
{
|
|
return new Vector3( -X()/2, y, +Z()/2 );
|
|
}
|
|
else if ( 1 == index )
|
|
{
|
|
return new Vector3( +X()/2, y, +Z()/2 );
|
|
}
|
|
else if ( 2 == index )
|
|
{
|
|
return new Vector3( -X()/2, y, -Z()/2 );
|
|
}
|
|
else if ( 3 == index )
|
|
{
|
|
return new Vector3( +X()/2, y, -Z()/2 );
|
|
}
|
|
|
|
return Vector3.Zero;
|
|
|
|
}
|
|
|
|
public Vector3 GetPointAt( int index )
|
|
{
|
|
// 00-03 4 Top Face
|
|
// 04-11 8 Top Edges
|
|
// 12-19 8 Bottom Edges
|
|
// 20-23 4 Bottom Face
|
|
|
|
if ( index < 4 )
|
|
{
|
|
return GetFacePoint( index, true );
|
|
}
|
|
else if ( index < 12 )
|
|
{
|
|
return GetEdgePoint( index - 4, true );
|
|
}
|
|
else if ( index < 20 )
|
|
{
|
|
return GetEdgePoint( index - 12, false );
|
|
}
|
|
else if ( index < 24 )
|
|
{
|
|
return GetFacePoint( index - 20, false );
|
|
}
|
|
|
|
return Vector3.Zero;
|
|
}
|
|
|
|
Vector3 GetFacePoint( int index, bool top )
|
|
{
|
|
var cornerPoint = GetBoundingCornerAt( index, top );
|
|
|
|
var offset = Vector3.Zero;
|
|
|
|
if ( 0 == index )
|
|
{
|
|
offset = GetOffsetFor( 1, -1 );
|
|
}
|
|
else if ( 1 == index )
|
|
{
|
|
offset = GetOffsetFor( -1, -1 );
|
|
}
|
|
else if ( 2 == index )
|
|
{
|
|
offset = GetOffsetFor( 1, 1 );
|
|
}
|
|
else if ( 3 == index )
|
|
{
|
|
offset = GetOffsetFor( -1, 1 );
|
|
}
|
|
|
|
return cornerPoint + offset;
|
|
}
|
|
|
|
Vector3 GetEdgePoint( int index, bool top )
|
|
{
|
|
var cornerIndex = index / 2;
|
|
var cornerPoint = GetBoundingCornerAt( cornerIndex, top );
|
|
|
|
if ( top )
|
|
{
|
|
cornerPoint.Y -= borderSize;
|
|
}
|
|
else
|
|
{
|
|
cornerPoint.Y += borderSize;
|
|
}
|
|
|
|
var offset = Vector3.Zero;
|
|
|
|
if ( 0 == cornerIndex )
|
|
{
|
|
offset = index == 0 ? GetOffsetFor( 0, -1 ) : GetOffsetFor( 1, 0 );
|
|
}
|
|
else if ( 1 == cornerIndex )
|
|
{
|
|
offset = index == 2 ? GetOffsetFor( -1, 0 ) : GetOffsetFor( 0, -1 );
|
|
}
|
|
else if ( 2 == cornerIndex )
|
|
{
|
|
offset = index == 4 ? GetOffsetFor( 0, 1 ) : GetOffsetFor( 1, 0 );
|
|
}
|
|
else if ( 3 == cornerIndex )
|
|
{
|
|
offset = index == 6 ? GetOffsetFor( -1, 0 ) : GetOffsetFor( 0, 1 );
|
|
}
|
|
|
|
return cornerPoint + offset;
|
|
}
|
|
|
|
}
|
|
|
|
} |