Transform/Grass Udpate

This commit is contained in:
Josef 2025-05-14 14:31:32 +02:00
parent 4f496cc7cc
commit 7de06b4bcd
26 changed files with 879 additions and 126 deletions

View File

@ -226,6 +226,18 @@ namespace Rokojori
return CreateChildIn<T>( parent, name );
}
public static T GetOrCreateChild<T>( this Node parent, string name = null ) where T:Node,new()
{
var child = Nodes.GetDirectChild<T>( parent );
if ( child == null )
{
child = parent.CreateChild<T>( name );
}
return child;
}
public static T CreateChildLocal3D<T>( this Node parent, Vector3 position, Quaternion? rotation, string name = null ) where T:Node3D,new()
{
var c = CreateChildIn<T>( parent, name );

View File

@ -78,6 +78,11 @@ namespace Rokojori
return new Vector3( v.X, 0, v.Y );
}
public static Vector3 XY( Vector2 v )
{
return new Vector3( v.X, v.Y, 0.0f );
}
public static float Dot( Vector3 a, Vector3 b )
{
return a.Dot( b );
@ -487,6 +492,25 @@ namespace Rokojori
node.LookAt( forward + node.GlobalPosition, up );
}
public static bool IsZero( this Quaternion q )
{
return q.X == 0 && q.Y == 0 && q.Z == 0 && q.W == 0;
}
public static bool IsValid( this Quaternion q )
{
return ! ( q.IsFinite() || q.IsZero() );
}
public static Quaternion GetNormalized( this Quaternion q )
{
if ( q.IsValid() )
{
return Quaternion.Identity;
}
return q.Normalized();
}
public static Quaternion GetDifference( this Quaternion q, Quaternion other )
{

View File

@ -13,6 +13,11 @@ namespace Rokojori
[Export]
public float yawOffset = 0;
[Export]
public MeshAxisSubDivider uSubDivisions;
[Export]
public MeshAxisSubDivider vSubDivisions;
public override int GetNumViews()
{
return useDoubleSidedMaterial ? 1 : 2;
@ -45,6 +50,7 @@ namespace Rokojori
var angle = yawOffset;
for ( int i = 0; i < numTextures; i++ )
{
var index = i;
@ -54,8 +60,15 @@ namespace Rokojori
var uv = TextureMerger.GetUVRectangle( textureAlignment, index, true );
var q = new MeshGeometry();
q.AddQuad( bakerCameras[ index ].viewSettings.bakingRotation, outputScale, uv.min, uv.max );
var transform3D = Math3D.TRS( Vector3.Zero, bakerCameras[ index ].viewSettings.bakingRotation, Vector3.One * outputScale );
var uDivisions = MeshAxisSubDivider.GetSubDivisionsU( uSubDivisions, transform3D );
var vDivisions = MeshAxisSubDivider.GetSubDivisionsV( vSubDivisions, transform3D );
q.AddQuadWithCustomDivisions( bakerCameras[ index ].viewSettings.bakingRotation, outputScale, uv.min, uv.max, uDivisions, vDivisions );
mg.Add( q );

View File

@ -0,0 +1,30 @@
using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
using System.Threading.Tasks;
using System.Linq;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class GridSubDivider:MeshAxisSubDivider
{
[Export]
public int numSubDivisions = 1;
public override List<float> GetSubDivisions( Transform3D quadTransform, Axis axis )
{
var list = new List<float>();
for ( int i = 0; i < numSubDivisions; i++ )
{
float s = (float)( i + 1f ) / (float)( numSubDivisions + 1f );
}
return list;
}
}
}

View File

@ -0,0 +1 @@
uid://h3oc6p4vkn8o

View File

@ -0,0 +1,64 @@
using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
using System.Threading.Tasks;
using System.Linq;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class ManualAbsoluteSubDivider:MeshAxisSubDivider
{
public enum SourceAxis
{
X,
Y,
Z
}
[Export]
public SourceAxis sourceAxis;
[Export]
public float[] subDivisions;
public override List<float> GetSubDivisions( Transform3D quadTransform, Axis axis )
{
var min = GetWorldMin( quadTransform );
var max = GetWorldMax( quadTransform );
var minV = min.X;
var maxV = max.X;
if ( SourceAxis.Y == sourceAxis )
{
minV = min.Y;
maxV = max.Y;
}
if ( SourceAxis.Z == sourceAxis )
{
minV = min.Z;
maxV = max.Z;
}
var list = new List<float>();
for ( int i = 0; i < subDivisions.Length; i++ )
{
var mapped = MathX.Normalize( list[ i ], minV, maxV );
if ( mapped <= 0 || mapped >= 1 )
{
continue;
}
list.Add( mapped );
}
return list;
}
}
}

View File

@ -0,0 +1 @@
uid://b8lfjqpaqj8px

View File

@ -0,0 +1,23 @@
using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
using System.Threading.Tasks;
using System.Linq;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class ManualRelativeSubDivider:MeshAxisSubDivider
{
[Export]
public float[] subDivisions;
public override List<float> GetSubDivisions( Transform3D quadTransform, Axis axis )
{
return Lists.From( subDivisions );
}
}
}

View File

@ -0,0 +1 @@
uid://bf5p6mxka0yen

View File

@ -0,0 +1,65 @@
using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
using System.Threading.Tasks;
using System.Linq;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class MeshAxisSubDivider:Resource
{
public enum Axis
{
U,
V
}
public virtual List<float> GetSubDivisions( Transform3D quadTransform, Axis axis )
{
return new List<float>();
}
public Vector3 GetWorldMin( Transform3D worldTransform )
{
return worldTransform * new Vector3( -0.5f, -0.5f, 0.0f);
}
public Vector3 GetWorldMax( Transform3D worldTransform )
{
return worldTransform * new Vector3( 0.5f, 0.5f, 0.0f);
}
public Vector3 AxisToVector( Axis a, float t = 1)
{
var d = Mathf.Lerp( -0.5f, 0.5f, t );
var v = Axis.U == a ? new Vector3( d, 0, 0 ) : new Vector3( 0, d, 0 );
return v;
}
public static List<float> GetSubDivisions( MeshAxisSubDivider divider, Transform3D quadTransform, Axis axis )
{
if ( divider == null )
{
return new List<float>(){};
}
return divider.GetSubDivisions( quadTransform, axis );
}
public static List<float> GetSubDivisionsU( MeshAxisSubDivider divider, Transform3D quadTransform )
{
return GetSubDivisions( divider, quadTransform, Axis.U );
}
public static List<float> GetSubDivisionsV( MeshAxisSubDivider divider, Transform3D quadTransform )
{
return GetSubDivisions( divider, quadTransform, Axis.V );
}
}
}

View File

@ -0,0 +1 @@
uid://bv6l2kx1pkyf1

View File

@ -36,14 +36,19 @@ namespace Rokojori
material.SetShaderParameter( "isFullSphere", octahedralFullSphere );
material.SetShaderParameter( "imposterFrames", Vector2.One * octahedralSides );
Materials.Set( mb.X_outputMesh, material );
// Materials.Set( mb.X_outputMesh, material );
MaterialSurfaceContainer.SetMaterialInSlot( mb.X_outputMesh, MaterialSlot.MeshSurface, material );
}
public override void AssignMaterial( List<_XX_BakingPass> passes )
{
var mb = multiBaker;
var material = Materials.Get<ShaderMaterial>( mb.X_outputMesh );
// var material = Materials.Get<ShaderMaterial>( mb.X_outputMesh );
var material = MaterialSurfaceContainer.GetMaterialInSlot<ShaderMaterial>( mb.X_outputMesh, MaterialSlot.MeshSurface );
if ( material == null )
{

View File

@ -33,13 +33,16 @@ namespace Rokojori
material.CullMode = BaseMaterial3D.CullModeEnum.Disabled;
}
Materials.Set( mb.X_outputMesh, material );
MaterialSurfaceContainer.SetMaterialInSlot( mb.X_outputMesh, MaterialSlot.MeshSurface, material );
// Materials.Set( mb.X_outputMesh, material );
}
public override void AssignMaterial( List<_XX_BakingPass> passes )
{
var mb = multiBaker;
var material = Materials.Get<StandardMaterial3D>( mb.X_outputMesh );
// var material = Materials.Get<StandardMaterial3D>( mb.X_outputMesh );
var material = MaterialSurfaceContainer.GetMaterialInSlot<StandardMaterial3D>( mb.X_outputMesh, MaterialSlot.MeshSurface );
material.AlbedoTexture = _XX_BakingPass.Get( passes, BakingTargetType.Albedo, BakingTargetType.Lit );

View File

@ -7,8 +7,6 @@ using System;
namespace Rokojori
{
public abstract class MaterialSurfaceContainer
{
public enum MaterialSlot
{
None,
@ -18,6 +16,10 @@ namespace Rokojori
Overlay
}
public abstract class MaterialSurfaceContainer
{
protected Node3D _owner;
protected int _surfaceIndex;
public int surfaceIndex => _surfaceIndex;
@ -29,7 +31,7 @@ namespace Rokojori
}
public abstract MaterialSlot GetActiveMaterialSlot();
public abstract Material GetMaterialInSlot( MaterialSlot slot );
public abstract T GetMaterialInSlot<T>( MaterialSlot slot ) where T:Material;
public abstract void SetMaterialInSlot( MaterialSlot slot, Material material );
public void SetActiveMaterial( Material material )
@ -37,9 +39,9 @@ namespace Rokojori
SetMaterialInSlot( GetActiveMaterialSlot(), material );
}
public Material GetActiveMaterial()
public T GetActiveMaterial<T>() where T:Material
{
return GetMaterialInSlot( GetActiveMaterialSlot() );
return (T)GetMaterialInSlot<T>( GetActiveMaterialSlot() );
}
protected abstract void _MakeUnique( bool materials );
@ -86,7 +88,48 @@ namespace Rokojori
public abstract int numSurfaces { get; }
public static void SetMaterialInSlot( Node3D owner, MaterialSlot slot, Material material, int surfaceIndex = 0 )
{
var mc = From( owner, surfaceIndex );
if ( mc == null )
{
return;
}
mc.SetMaterialInSlot( slot, material );
}
public static T GetMaterialInSlot<T>( Node3D owner, MaterialSlot slot, int surfaceIndex = 0 ) where T:Material
{
var mc = From( owner, surfaceIndex );
if ( mc == null )
{
return null;
}
return mc.GetMaterialInSlot<T>( slot );
}
public static MaterialSurfaceContainer From( Node3D owner, int surfaceIndex = -1 )
{
if ( owner is MeshInstance3D mesh )
{
return new MeshSurfaceContainer( mesh, surfaceIndex );
}
if ( owner is MultiMeshInstance3D multi )
{
return new MultiMeshSurfaceContainer( multi, surfaceIndex );
}
return null;
}
}
public abstract class MaterialSurfaceContainer<T>:MaterialSurfaceContainer where T:Node3D
@ -102,26 +145,26 @@ namespace Rokojori
public override int numSurfaces => node == null || node.Mesh == null ? -1 : node.Mesh.GetSurfaceCount();
public override MeshSurfaceContainer.MaterialSlot GetActiveMaterialSlot()
public override MaterialSlot GetActiveMaterialSlot()
{
if ( node.MaterialOverride != null )
{
return MeshSurfaceContainer.MaterialSlot.Override;
return MaterialSlot.Override;
}
if ( node.Mesh == null || surfaceIndex == -1 )
{
return MeshSurfaceContainer.MaterialSlot.None;
return MaterialSlot.None;
}
if ( node.GetSurfaceOverrideMaterial( surfaceIndex ) != null )
{
return MeshSurfaceContainer.MaterialSlot.MeshSurfaceOverride;
return MaterialSlot.MeshSurfaceOverride;
}
var material = node.Mesh.SurfaceGetMaterial( surfaceIndex );
return material == null ? MeshSurfaceContainer.MaterialSlot.None : MeshSurfaceContainer.MaterialSlot.MeshSurface;
return material == null ? MaterialSlot.None : MaterialSlot.MeshSurface;
}
public override void SetMaterialInSlot( MaterialSlot slot, Material material )
@ -149,7 +192,7 @@ namespace Rokojori
}
}
public override Material GetMaterialInSlot( MaterialSlot slot )
public override T GetMaterialInSlot<T>( MaterialSlot slot )
{
if ( MaterialSlot.None == slot )
{
@ -157,19 +200,19 @@ namespace Rokojori
}
else if ( MaterialSlot.MeshSurface == slot )
{
return node.Mesh.SurfaceGetMaterial( surfaceIndex );
return (T) node.Mesh.SurfaceGetMaterial( surfaceIndex );
}
else if ( MaterialSlot.MeshSurfaceOverride == slot )
{
return node.GetSurfaceOverrideMaterial( surfaceIndex );
return (T) node.GetSurfaceOverrideMaterial( surfaceIndex );
}
else if ( MaterialSlot.Override == slot )
{
return node.MaterialOverride;
return (T) node.MaterialOverride;
}
else if ( MaterialSlot.Overlay == slot )
{
return node.MaterialOverlay;
return (T) node.MaterialOverlay;
}
return null;
@ -210,22 +253,22 @@ namespace Rokojori
public override int numSurfaces => node == null || node.Multimesh == null || node.Multimesh.Mesh == null ? -1 :
node.Multimesh.Mesh.GetSurfaceCount();
public override MeshSurfaceContainer.MaterialSlot GetActiveMaterialSlot()
public override MaterialSlot GetActiveMaterialSlot()
{
if ( node.MaterialOverride != null )
{
return MeshSurfaceContainer.MaterialSlot.Override;
return MaterialSlot.Override;
}
if ( node.Multimesh == null || node.Multimesh.Mesh == null || surfaceIndex == -1 )
{
return MeshSurfaceContainer.MaterialSlot.None;
return MaterialSlot.None;
}
var material = node.Multimesh.Mesh.SurfaceGetMaterial( surfaceIndex );
return material == null ? MeshSurfaceContainer.MaterialSlot.None : MeshSurfaceContainer.MaterialSlot.MeshSurface;
return material == null ? MaterialSlot.None : MaterialSlot.MeshSurface;
}
public override void SetMaterialInSlot( MaterialSlot slot, Material material )
@ -249,7 +292,7 @@ namespace Rokojori
}
}
public override Material GetMaterialInSlot( MaterialSlot slot )
public override T GetMaterialInSlot<T>( MaterialSlot slot )
{
if ( MaterialSlot.None == slot )
{
@ -257,15 +300,15 @@ namespace Rokojori
}
else if ( MaterialSlot.MeshSurface == slot )
{
return node.Multimesh.Mesh.SurfaceGetMaterial( surfaceIndex );
return (T) node.Multimesh.Mesh.SurfaceGetMaterial( surfaceIndex );
}
else if ( MaterialSlot.Override == slot )
{
return node.MaterialOverride;
return (T) node.MaterialOverride;
}
else if ( MaterialSlot.Overlay == slot )
{
return node.MaterialOverlay;
return (T) node.MaterialOverlay;
}
return null;

View File

@ -0,0 +1 @@
uid://bk3iamd4q3siu

View File

@ -48,7 +48,7 @@ namespace Rokojori
}
[Export]
public TextureSizeMode textureSizeMode = TextureSizeMode.Custom;
public TextureSizeMode textureSizeMode = TextureSizeMode.KeepOriginal;
[Export]
public Vector2I customTextureSize = new Vector2I( 1024, 1024 );
@ -111,14 +111,8 @@ namespace Rokojori
await CombineMaterials();
if ( combineMeshes )
{
await CombineMeshes();
}
else
{
await ReassignMaterials();
}
}
@ -176,6 +170,12 @@ namespace Rokojori
if ( type == null )
{
type = MaterialType.From( m );
if ( type == null )
{
this.LogInfo( "Invalid Type:", m);
}
}
if ( type == null )
@ -337,47 +337,6 @@ namespace Rokojori
return outputMaterial;
}
async Task ReassignMaterials()
{
if ( outputContainer == null )
{
outputContainer = this.CreateChild<Node3D>();
}
outputContainer.DestroyChildren();
foreach ( var n in sourceNodes )
{
var root = n.DeepCopyTo( outputContainer );
var materialContainers = MeshExtractor.ExtractMaterialContainersInHierarchy( root, null, true );
materialContainers.ForEach(
mc =>
{
mc.MakeUnique( false );
mc.ForAllSurfaces(
( surface )=>
{
var slot = surface.GetActiveMaterialSlot();
if ( MaterialSurfaceContainer.MaterialSlot.None == slot )
{
return;
}
var material = surface.GetActiveMaterial();
if ( _combinedMaterials.ContainsKey( material ) )
{
surface.SetActiveMaterial( _combinedMaterials[ material ] );
}
}
);
}
);
}
}
async Task CombineMeshes()
{
var arrayMesh = new ArrayMesh();
@ -390,14 +349,27 @@ namespace Rokojori
var outputMaterials = new List<Material>();
if ( ! combineMeshes )
{
if ( outputContainer == null )
{
outputContainer = this.CreateChild<Node3D>();
}
outputContainer.DestroyChildren();
}
_materials.ForEach(
( m )=>
{
var isCombinedMaterial = _combinedMaterials.ContainsKey( m );
var usedMaterial = isCombinedMaterial ? _combinedMaterials[ m ] : m;
Transform2D? uvTransform = _uvTransform.ContainsKey( m ) ? _uvTransform[ m ] : null;
var surfaces = _materiaList[ m ];
this.LogInfo( "Combining for Material", m, surfaces.Count, "meshes" );
this.LogInfo( "Combining for Material", "combined?:",isCombinedMaterial,"material:", usedMaterial, surfaces.Count, "meshes" );
var meshGeometry = new MeshGeometry();
@ -414,32 +386,54 @@ namespace Rokojori
var trsf = s.transform;
if ( combineMeshes )
{
if ( pivot != null )
{
trsf.Origin -= pivot.GlobalPosition;
}
smg.ApplyTransform( trsf );
}
meshGeometry.Add( smg );
if ( isCombinedMaterial && ! combineMeshes )
{
meshGeometry.GenerateMesh( Mesh.PrimitiveType.Triangles, arrayMesh );
arrayMesh.SurfaceSetMaterial( index, usedMaterial );
var meshInstance = outputContainer.CreateChild<MeshInstance3D>();
meshInstance.Mesh = arrayMesh;
meshInstance.GlobalTransform = trsf;
meshGeometry = new MeshGeometry();
arrayMesh = new ArrayMesh();
}
}
);
var isCombinedMaterial = _combinedMaterials.ContainsKey( m );
if ( isCombinedMaterial )
if ( isCombinedMaterial && combineMeshes )
{
this.LogInfo( "Add material groups", m );
combined.Add( _combinedMaterials[ m ], meshGeometry );
return;
}
outputMaterials.Add( usedMaterial );
if ( combineMeshes )
{
meshGeometry.GenerateMesh( Mesh.PrimitiveType.Triangles, arrayMesh );
arrayMesh.SurfaceSetMaterial( index, usedMaterial );
arrayMesh.SurfaceSetMaterial( index, m );
outputMaterials.Add( m );
index ++;
}
}
);
@ -468,17 +462,20 @@ namespace Rokojori
this.LogInfo( "Processing done, adding outputs", arrayMesh.GetSurfaceCount() );
this.outputMaterials = outputMaterials.ToArray();
if ( combineMeshes )
{
if ( outputMesh == null )
{
this.LogInfo( "Created outputMesh");
outputMesh = this.CreateChild<MeshInstance3D>();
}
this.outputMaterials = outputMaterials.ToArray();
outputMesh.Mesh = arrayMesh;
}
return;
}

View File

@ -158,14 +158,14 @@ namespace Rokojori
return list;
}
public static List<Transformable<MeshSurface>> ExtractSurfaces( Node n, List<Transformable<MeshSurface>> list = null, bool trackOwners = false )
public static List<Transformable<MeshSurface>> ExtractSurfaces( Node n, List<Transformable<MeshSurface>> list = null )
{
list = list == null ? new List<Transformable<MeshSurface>>() : list;
if ( n is MeshInstance3D mi )
{
var owner = trackOwners ? mi : null;
var owner = mi;
var mesh = mi.Mesh;
@ -189,7 +189,7 @@ namespace Rokojori
if ( n is MultiMeshInstance3D mmi )
{
var owner = trackOwners ? mmi : null;
var owner = mmi;
var mm = mmi.Multimesh;
for ( var j = 0; j < mm.InstanceCount; j++ )

View File

@ -660,6 +660,21 @@ namespace Rokojori
AddTriangle( va, vb, vc, n, n, n, uv, uv, uv );
}
public void AddQuad(
VertexAttributes a,
VertexAttributes b,
VertexAttributes c,
VertexAttributes d
)
{
AddQuad(
a.position, b.position, c.position, d.position,
(Vector3) a.normal, (Vector3) b.normal, (Vector3) c.normal, (Vector3) d.normal,
(Vector2) a.uv, (Vector2) b.uv, (Vector2) c.uv, (Vector2) d.uv
);
}
public void AddQuad(
Vector3 va, Vector3 vb, Vector3 vc, Vector3 vd,
Vector3 na, Vector3 nb, Vector3 nc, Vector3 nd,
@ -667,6 +682,18 @@ namespace Rokojori
)
{
/*
0:a -- 1:b
| |
2:c -- 3:d
faces:
1: 0 1 2
2: 2 3 0
*/
var index = vertices.Count;
Lists.Add( vertices, va, vb, vc, vd );
@ -675,8 +702,10 @@ namespace Rokojori
Lists.Add( indices, index, index + 1, index + 2 );
Lists.Add( indices, index + 2, index + 3, index );
}
public void AddQuad( Quaternion rotation, float size, Box2 rectangle )
{
AddQuad( rotation, size, rectangle.min, rectangle.max );
@ -702,6 +731,112 @@ namespace Rokojori
}
}
public void AddQuadWithCustomDivisions( Quaternion rotation, float size, Vector2 uv00, Vector2 uv11, List<float> uDivisions, List<float> vDivisions )
{
if ( uDivisions.Count == 0 && vDivisions.Count == 0 )
{
AddQuad( rotation, size, uv00, uv11 );
return;
}
var l = size * 0.5f;
var normal = Vector3.Back * rotation;
var points = new List<Vector3>
{
new Vector3( l, -l, 0 ), new Vector3( -l, -l, 0 ),
new Vector3( -l, l, 0 ), new Vector3( l, l, 0 )
};
for ( int i = 0; i < points.Count; i++ )
{
points[ i ] = points[ i ] * rotation;
}
var uv10 = new Vector2( uv11.X, uv00.Y );
var uv01 = new Vector2( uv00.X, uv11.Y );
var v10 = VertexAttributes.Create( points[ 0 ], uv10, normal );
var v00 = VertexAttributes.Create( points[ 1 ], uv00, normal );
var v01 = VertexAttributes.Create( points[ 2 ], uv01, normal );
var v11 = VertexAttributes.Create( points[ 3 ], uv11, normal );
var uSegments = new List<float>();
uSegments.Add( 0 );
uSegments.AddRange( uDivisions );
uSegments.Add( 1 );
var vSegments = new List<float>();
vSegments.Add( 0 );
vSegments.AddRange( vDivisions );
vSegments.Add( 1 );
for ( int i = 0; i < ( uSegments.Count - 1 ); i++ )
{
var i0 = uSegments[ i ];
var i1 = uSegments[ i + 1 ];
var t0 = v10.Lerp( v00, i0 );
var t1 = v10.Lerp( v00, i1 );
var b0 = v01.Lerp( v11, i0 );
var b1 = v01.Lerp( v11, i1 );
for ( int j = 0; j < ( vSegments.Count - 1 ); j++ )
{
var j0 = vSegments[ j ];
var j1 = vSegments[ j + 1 ];
var tb00 = t0.Lerp( b0, j0 );
var tb10 = t1.Lerp( b1, j0 );
var tb01 = t0.Lerp( b0, j1 );
var tb11 = t1.Lerp( b1, j1 );
AddQuad( tb10, tb00, tb01, tb11 );
}
}
}
public void AddQuadSubdivided( Quaternion rotation, float size, Vector2 uv00, Vector2 uv11, int uDivisions = 0, int vDivisions = 0 )
{
uDivisions = Mathf.Max( 0, uDivisions );
vDivisions = Mathf.Max( 0, vDivisions );
if ( uDivisions == 0 && vDivisions == 0 )
{
AddQuad( rotation, size, uv00, uv11 );
return;
}
var mg = CreateFromUVFunction(
( uv ) =>
{
var xy = uv * size - Vector2.One * size / 2f;
var pose = new Pose();
pose.position = Math3D.XY( xy );
pose.rotation = rotation;
return pose;
},
uDivisions + 2, vDivisions + 2
);
var uvTransform = new Transform2D();
uvTransform.Origin = uv00;
uvTransform = uvTransform.ScaledLocal( uv11 - uv00 );
mg.ApplyUVTransform( uvTransform );
Add( mg );
}
public void AddQuad( Quaternion rotation, float size, Vector2 uv00, Vector2 uv11 )
{
var l = size * 0.5f;

View File

@ -0,0 +1,57 @@
using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
namespace Rokojori
{
public class VertexAttributes
{
public Vector3 position;
public Vector3? normal;
public Vector2? uv;
public Vector2? uv2 = null;
public Color? color = null;
public static VertexAttributes Create( Vector3 position, Vector2 uv, Vector3 normal )
{
var va = new VertexAttributes();
va.position = position;
va.uv = uv;
va.normal = normal;
return va;
}
public VertexAttributes Lerp( VertexAttributes other, float t )
{
var lerped = new VertexAttributes();
lerped.position = position.Lerp( other.position, t );
if ( normal != null )
{
lerped.normal = ((Vector3)normal).Lerp( (Vector3)other.normal, t );
}
if ( uv != null )
{
lerped.uv = ((Vector2)uv).Lerp( (Vector2)other.uv, t );
}
if ( uv2 != null )
{
lerped.uv2 = ((Vector2)uv2).Lerp( (Vector2)other.uv2, t );
}
if ( color != null )
{
lerped.color = ((Color)color).Lerp( (Color)other.color, t );
}
return lerped;
}
}
}

View File

@ -0,0 +1 @@
uid://sskx2gnmrilv

View File

@ -50,11 +50,11 @@ namespace Rokojori
if ( useGlobalRotation )
{
Math3D.SetGlobalRotationTo( node3D, rotation.Normalized() );
Math3D.SetGlobalRotationTo( node3D, rotation.GetNormalized() );
}
else
{
node3D.Quaternion = rotation;
node3D.Quaternion = rotation.GetNormalized();
}
node3D.Scale = scale;

View File

@ -63,7 +63,7 @@ namespace Rokojori
public void CopyFromSampled( TextureCombinerBuffer source, int x, int y, int w, int h )
{
RJLog.Log( "Copy Sampled", x,y, w, h );
// RJLog.Log( "Copy Sampled", x,y, w, h );
for ( int i = 0; i < w; i ++ )
{
@ -92,7 +92,7 @@ namespace Rokojori
var mergeSize = new Vector2( w, h );
var gridSize = (Vector2I)( mergeSize / alignment );
RJLog.Log( "GridMerge" );
// RJLog.Log( "GridMerge" );
for ( int i = 0; i < textures.Count; i++ )
{
@ -101,7 +101,7 @@ namespace Rokojori
positions.Add( position );
sizes.Add( gridSize );
RJLog.Log( i, position, gridSize );
// RJLog.Log( i, position, gridSize );
}

View File

@ -0,0 +1,153 @@
vec4 quaternionFromMatrix( mat3 m )
{
vec4 qa = vec4( 0.0, 0.0, 0.0, 1.0 );
float trace = m[ 0 ][ 0 ] + m[ 1 ][ 1 ] + m[ 2 ][ 2 ];
if ( trace > 0.0 )
{
float s = 0.5 / sqrt( trace + 1.0 );
qa.w = 0.25 / s;
qa.x = ( m[ 1 ][ 2 ] - m[ 2 ][ 1 ] ) * s;
qa.y = ( m[ 2 ][ 0 ] - m[ 0 ][ 2 ] ) * s;
qa.z = ( m[ 0 ][ 1 ] - m[ 1 ][ 0 ] ) * s;
}
else if ( m[ 0 ][ 0 ] > m[ 1 ][ 1 ] && m[ 0 ][ 0 ] > m[ 2 ][ 2 ] )
{
float s = 2.0 * sqrt( 1.0 + m[ 0 ][ 0 ] - m[ 1 ][ 1 ] - m[ 2 ][ 2 ] );
qa.w = ( m[ 1 ][ 2 ] - m[ 2 ][ 1 ] ) / s;
qa.x = 0.25 * s;
qa.y = ( m[ 1 ][ 0 ] + m[ 0 ][ 1 ] ) / s;
qa.z = ( m[ 2 ][ 0 ] + m[ 0 ][ 2 ] ) / s;
}
else if ( m[ 1 ][ 1 ] > m[ 2 ][ 2 ] )
{
float s = 2.0 * sqrt( 1.0 + m[ 1 ][ 1 ] - m[ 0 ][ 0 ] - m[ 2 ][ 2 ] );
qa.w = ( m[ 2 ][ 0 ] - m[ 0 ][ 2 ] ) / s;
qa.x = ( m[ 1 ][ 0 ] + m[ 0 ][ 1 ] ) / s;
qa.y = 0.25 * s;
qa.z = ( m[ 2 ][ 1 ] + m[ 1 ][ 2 ] ) / s;
}
else
{
float s = 2.0 * sqrt( 1.0 + m[ 2 ][ 2 ] - m[ 0 ][ 0 ] - m[ 1 ][ 1 ] );
qa.w = ( m[ 0 ][ 1 ] - m[ 1 ][ 0 ] ) / s;
qa.x = ( m[ 2 ][ 0 ] + m[ 0 ][ 2 ] ) / s;
qa.y = ( m[ 2 ][ 1 ] + m[ 1 ][ 2 ] ) / s;
qa.z = 0.25 * s;
}
return qa;
}
vec4 quaternionMultiply( vec4 a, vec4 b )
{
// from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
float qax = a.x;
float qay = a.y;
float qaz = a.z;
float qaw = a.w;
float qbx = b.x;
float qby = b.y;
float qbz = b.z;
float qbw = b.w;
vec4 q = vec4( 0.0, 0.0, 0.0, 0.0 );
q.x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
q.y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
q.z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
q.w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
return q;
}
vec4 quaternionSlerp( vec4 qa, vec4 qb, float t )
{
if ( t == 0.0 )
{
return qa;
}
if ( t == 1.0 )
{
return qb;
}
float x = qa.x;
float y = qa.y;
float z = qa.z;
float w = qa.w;
float cosHalfTheta = w * qb.w + x * qb.x + y * qb.y + z * qb.z;
if ( cosHalfTheta < 0.0 )
{
qa.w = - qb.w;
qa.x = - qb.x;
qa.y = - qb.y;
qa.z = - qb.z;
cosHalfTheta = - cosHalfTheta;
}
else
{
qa = qb;
}
if ( cosHalfTheta >= 1.0 )
{
qa.w = w;
qa.x = x;
qa.y = y;
qa.z = z;
return qa;
}
float sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta;
if ( sqrSinHalfTheta <= 0.000001 )
{
float s = 1.0 - t;
qa.w = s * w + t * qa.w;
qa.x = s * x + t * qa.x;
qa.y = s * y + t * qa.y;
qa.z = s * z + t * qa.z;
qa = normalize( qa );
return qa;
}
float sinHalfTheta = sqrt( sqrSinHalfTheta );
float halfTheta = atan( sinHalfTheta, cosHalfTheta );
float ratioA = sin( ( 1.0 - t ) * halfTheta ) / sinHalfTheta;
float ratioB = sin( t * halfTheta ) / sinHalfTheta;
qa.w = ( w * ratioA + qa.w * ratioB );
qa.x = ( x * ratioA + qa.x * ratioB );
qa.y = ( y * ratioA + qa.y * ratioB );
qa.z = ( z * ratioA + qa.z * ratioB );
return qa;
}

View File

@ -0,0 +1 @@
uid://c6trfbv30psqx

View File

@ -1,3 +1,4 @@
#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Quaternion.gdshaderinc"
vec3 applyMatrix( vec3 v, mat4 m )
{
@ -43,7 +44,7 @@ vec3 localToViewDirection( vec3 local, mat3 _MODELVIEW_NORMAL_MATRIX )
vec3 worldToLocal( vec3 world, mat4 _MODEL_MATRIX )
{
mat4 inversedMatrix = inverse( _MODEL_MATRIX );
return applyMatrix( world, inv );
return applyMatrix( world, inversedMatrix );
}
vec3 worldToLocalDirection( vec3 world, mat4 _MODEL_MATRIX )
@ -142,9 +143,14 @@ vec2 worldToScreen( vec3 world, mat4 _VIEW_MATRIX, mat4 _PROJECTION_MATRIX )
}
vec3 extractScale( mat3 _MODEL_NORMAL_MATRIX )
vec3 extractTranslation( mat4 matrix )
{
mat3 m = _MODEL_NORMAL_MATRIX;
return vec3( matrix[ 3 ][ 0 ], matrix[ 3 ][ 1 ], matrix[ 3 ][ 2 ] );
}
vec3 extractScale( mat3 matrix )
{
mat3 m = matrix;
float x = length( vec3( m[ 0 ][ 0 ], m[ 1 ][ 0 ], m[ 2 ][ 0 ] ) );
float y = length( vec3( m[ 0 ][ 1 ], m[ 1 ][ 1 ], m[ 2 ][ 1 ] ) );
@ -153,6 +159,48 @@ vec3 extractScale( mat3 _MODEL_NORMAL_MATRIX )
return vec3( x, y, z );
}
vec3 extractScale( mat4 matrix )
{
mat4 m = matrix;
float x = length( vec3( m[ 0 ][ 0 ], m[ 1 ][ 0 ], m[ 2 ][ 0 ] ) );
float y = length( vec3( m[ 0 ][ 1 ], m[ 1 ][ 1 ], m[ 2 ][ 1 ] ) );
float z = length( vec3( m[ 0 ][ 2 ], m[ 1 ][ 2 ], m[ 2 ][ 2 ] ) );
return vec3( x, y, z );
}
mat3 extractRotationMatrix( mat4 m )
{
vec3 x = normalize( m[ 0 ].xyz );
vec3 y = normalize( m[ 1 ].xyz );
vec3 z = normalize( m[ 2 ].xyz );
return mat3( x, y, z );
}
vec4 extractQuaternion( mat4 m )
{
mat3 rotationMatrix = extractRotationMatrix( m );
return quaternionFromMatrix( rotationMatrix );
}
float extractRotationX( mat4 matrix )
{
return atan( matrix[2][1], matrix[2][2] );
}
float extractRotationY( mat4 matrix )
{
return atan(-matrix[2][0], sqrt(matrix[2][1] * matrix[2][1] + matrix[2][2] * matrix[2][2]));
}
float extractRotationZ( mat4 matrix )
{
return atan(matrix[1][0], matrix[0][0]);
}
vec2 tilingOffset( vec2 uv, vec4 tilingOffset )
{
uv *= tilingOffset.xy;
@ -378,13 +426,15 @@ mat4 identity_m4()
mat4 translate_m4( vec3 translation )
{
return mat4(
vec4( 1, 0, 0, translation.x ),
vec4( 0, 1, 0, translation.y ),
vec4( 0, 0, 1, translation.z ),
vec4( 0, 0, 0, 1 )
vec4( 1, 0, 0, 0 ),
vec4( 0, 1, 0, 0 ),
vec4( 0, 0, 1, 0 ),
vec4( translation.x , translation.y, translation.z, 1 )
);
}
mat4 scale_m4( vec3 scale )
{
return mat4(
@ -403,8 +453,8 @@ mat4 rotationX_m4( float radiansAngle )
return mat4(
vec4( 1, 0, 0, 0 ),
vec4( 0, c, -s, 0 ),
vec4( 0, s, c, 0 ),
vec4( 0, c, s, 0 ),
vec4( 0, -s, c, 0 ),
vec4( 0, 0, 0, 1 )
);
}
@ -415,9 +465,9 @@ mat4 rotationY_m4( float radiansAngle )
float s = sin( radiansAngle );
return mat4(
vec4( c, 0, s, 0 ),
vec4( c, 0,-s, 0 ),
vec4( 0, 1, 0, 0 ),
vec4( -s, 0, c, 0 ),
vec4( s, 0, c, 0 ),
vec4( 0, 0, 0, 1 )
);
}
@ -428,9 +478,81 @@ mat4 rotationZ_m4( float radiansAngle )
float s = sin( radiansAngle );
return mat4(
vec4( c, -s, 0, 0 ),
vec4( s, c, 0, 0 ),
vec4( c, s, 0, 0 ),
vec4(-s, c, 0, 0 ),
vec4( 0, 0, 1, 0 ),
vec4( 0, 0, 0, 1 )
);
}
mat3 quaternionToRotationMatrix( vec4 q )
{
float x = q.x;
float y = q.y;
float z = q.z;
float w = q.w;
float x2 = x + x;
float y2 = y + y;
float z2 = z + z;
float xx = x * x2;
float xy = x * y2;
float xz = x * z2;
float yy = y * y2;
float yz = y * z2;
float zz = z * z2;
float wx = w * x2;
float wy = w * y2;
float wz = w * z2;
mat3 matrix = mat3(
vec3(
( 1.0 - ( yy + zz ) ),
( xy + wz ),
( xz - wy )
),
vec3(
( xy - wz ),
( 1.0 - ( xx + zz ) ),
( yz + wx )
),
vec3(
( xz + wy ),
( yz - wx ),
( 1.0 - ( xx + yy ) )
)
);
return matrix;
}
mat4 TRS( vec3 translation, vec4 rotation, vec3 scale )
{
return translate_m4( translation ) * mat4( quaternionToRotationMatrix( rotation ) ) * scale_m4( scale );
}
mat4 mixTRS( mat4 a, mat4 b, float t )
{
vec3 oA = extractTranslation( a );
vec3 oB = extractTranslation( b );
vec3 sA = extractScale( a );
vec3 sB = extractScale( b );
vec4 rA = extractQuaternion( a );
vec4 rB = extractQuaternion( b );
vec3 o = mix( oA, oB, t );
vec3 s = mix( sA, sB, t );
vec4 r = quaternionSlerp( rA, rB, t );
return TRS( o, r, s );
}

View File

@ -28,7 +28,7 @@ leftButton = ExtResource("4_nn62x")
rightButton = ExtResource("7_r8nl0")
upButton = ExtResource("9_sydsp")
downButton = ExtResource("2_jknb0")
moveSpeed = 1.0
moveSpeed = 10.0
mouseMovementEnabled = true
minimizeDistanceOnMovement = true
mouseMovementYawSpeed = 0.2