From 7de06b4bcda948bddc50f02569485bf37a719d03 Mon Sep 17 00:00:00 2001 From: Josef Date: Wed, 14 May 2025 14:31:32 +0200 Subject: [PATCH] Transform/Grass Udpate --- Runtime/Godot/Nodes.cs | 12 ++ Runtime/Math/Math3D.cs | 24 +++ .../Baking/MultiBaker/Flat_Baker.cs | 17 +- .../MeshAxisSubDividers/GridSubDivider.cs | 30 ++++ .../MeshAxisSubDividers/GridSubDivider.cs.uid | 1 + .../ManualAbsoluteSubDivider.cs | 64 ++++++++ .../ManualAbsoluteSubDivider.cs.uid | 1 + .../ManualRelativeSubDivider.cs | 23 +++ .../ManualRelativeSubDivider.cs.uid | 1 + .../MeshAxisSubDividers/MeshAxisSubDivider.cs | 65 ++++++++ .../MeshAxisSubDivider.cs.uid | 1 + .../Baking/MultiBaker/Octahedral_Baker.cs | 9 +- .../_XX_MultiBakeModeBillboardBase.cs | 7 +- .../Mesh/MaterialSurfaceContainer.cs | 101 ++++++++---- .../Mesh/MaterialSurfaceContainer.cs.uid | 1 + Runtime/Procedural/Mesh/MeshCombiner.cs | 135 ++++++++-------- Runtime/Procedural/Mesh/MeshExtractor.cs | 6 +- Runtime/Procedural/Mesh/MeshGeometry.cs | 135 ++++++++++++++++ Runtime/Procedural/Mesh/VertexAttributes.cs | 57 +++++++ .../Procedural/Mesh/VertexAttributes.cs.uid | 1 + Runtime/Procedural/Points/PointData.cs | 4 +- .../TextureCombiner/TextureCombinerBuffer.cs | 6 +- .../Shading/Library/Quaternion.gdshaderinc | 153 ++++++++++++++++++ .../Library/Quaternion.gdshaderinc.uid | 1 + Runtime/Shading/Library/Transform.gdshaderinc | 148 +++++++++++++++-- .../MouseEditorCamera Default Inputs.tres | 2 +- 26 files changed, 879 insertions(+), 126 deletions(-) create mode 100644 Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/GridSubDivider.cs create mode 100644 Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/GridSubDivider.cs.uid create mode 100644 Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/ManualAbsoluteSubDivider.cs create mode 100644 Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/ManualAbsoluteSubDivider.cs.uid create mode 100644 Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/ManualRelativeSubDivider.cs create mode 100644 Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/ManualRelativeSubDivider.cs.uid create mode 100644 Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/MeshAxisSubDivider.cs create mode 100644 Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/MeshAxisSubDivider.cs.uid create mode 100644 Runtime/Procedural/Mesh/MaterialSurfaceContainer.cs.uid create mode 100644 Runtime/Procedural/Mesh/VertexAttributes.cs create mode 100644 Runtime/Procedural/Mesh/VertexAttributes.cs.uid create mode 100644 Runtime/Shading/Library/Quaternion.gdshaderinc create mode 100644 Runtime/Shading/Library/Quaternion.gdshaderinc.uid diff --git a/Runtime/Godot/Nodes.cs b/Runtime/Godot/Nodes.cs index c07adb3..8bdb146 100644 --- a/Runtime/Godot/Nodes.cs +++ b/Runtime/Godot/Nodes.cs @@ -226,6 +226,18 @@ namespace Rokojori return CreateChildIn( parent, name ); } + public static T GetOrCreateChild( this Node parent, string name = null ) where T:Node,new() + { + var child = Nodes.GetDirectChild( parent ); + + if ( child == null ) + { + child = parent.CreateChild( name ); + } + + return child; + } + public static T CreateChildLocal3D( this Node parent, Vector3 position, Quaternion? rotation, string name = null ) where T:Node3D,new() { var c = CreateChildIn( parent, name ); diff --git a/Runtime/Math/Math3D.cs b/Runtime/Math/Math3D.cs index 2d445b8..c3f105a 100644 --- a/Runtime/Math/Math3D.cs +++ b/Runtime/Math/Math3D.cs @@ -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 ); @@ -485,8 +490,27 @@ 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 ) { diff --git a/Runtime/Procedural/Baking/MultiBaker/Flat_Baker.cs b/Runtime/Procedural/Baking/MultiBaker/Flat_Baker.cs index b73752a..86994e2 100644 --- a/Runtime/Procedural/Baking/MultiBaker/Flat_Baker.cs +++ b/Runtime/Procedural/Baking/MultiBaker/Flat_Baker.cs @@ -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; @@ -44,6 +49,7 @@ namespace Rokojori var angle = yawOffset; + for ( int i = 0; i < numTextures; i++ ) { @@ -52,10 +58,17 @@ namespace Rokojori bakerCameras[ index ].viewSettings.yaw = angle + i * 180f; bakerCameras[ index ].viewSettings.pitch = 0; - var uv = TextureMerger.GetUVRectangle( textureAlignment, index, true ); + 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 ); diff --git a/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/GridSubDivider.cs b/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/GridSubDivider.cs new file mode 100644 index 0000000..af44ea1 --- /dev/null +++ b/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/GridSubDivider.cs @@ -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 GetSubDivisions( Transform3D quadTransform, Axis axis ) + { + var list = new List(); + + for ( int i = 0; i < numSubDivisions; i++ ) + { + float s = (float)( i + 1f ) / (float)( numSubDivisions + 1f ); + } + + return list; + } + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/GridSubDivider.cs.uid b/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/GridSubDivider.cs.uid new file mode 100644 index 0000000..5755636 --- /dev/null +++ b/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/GridSubDivider.cs.uid @@ -0,0 +1 @@ +uid://h3oc6p4vkn8o diff --git a/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/ManualAbsoluteSubDivider.cs b/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/ManualAbsoluteSubDivider.cs new file mode 100644 index 0000000..38850d6 --- /dev/null +++ b/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/ManualAbsoluteSubDivider.cs @@ -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 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(); + + 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; + } + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/ManualAbsoluteSubDivider.cs.uid b/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/ManualAbsoluteSubDivider.cs.uid new file mode 100644 index 0000000..d719530 --- /dev/null +++ b/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/ManualAbsoluteSubDivider.cs.uid @@ -0,0 +1 @@ +uid://b8lfjqpaqj8px diff --git a/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/ManualRelativeSubDivider.cs b/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/ManualRelativeSubDivider.cs new file mode 100644 index 0000000..7902f73 --- /dev/null +++ b/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/ManualRelativeSubDivider.cs @@ -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 GetSubDivisions( Transform3D quadTransform, Axis axis ) + { + return Lists.From( subDivisions ); + } + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/ManualRelativeSubDivider.cs.uid b/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/ManualRelativeSubDivider.cs.uid new file mode 100644 index 0000000..e00a085 --- /dev/null +++ b/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/ManualRelativeSubDivider.cs.uid @@ -0,0 +1 @@ +uid://bf5p6mxka0yen diff --git a/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/MeshAxisSubDivider.cs b/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/MeshAxisSubDivider.cs new file mode 100644 index 0000000..7b1b40a --- /dev/null +++ b/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/MeshAxisSubDivider.cs @@ -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 GetSubDivisions( Transform3D quadTransform, Axis axis ) + { + return new List(); + } + + 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 GetSubDivisions( MeshAxisSubDivider divider, Transform3D quadTransform, Axis axis ) + { + if ( divider == null ) + { + return new List(){}; + } + + return divider.GetSubDivisions( quadTransform, axis ); + } + + public static List GetSubDivisionsU( MeshAxisSubDivider divider, Transform3D quadTransform ) + { + return GetSubDivisions( divider, quadTransform, Axis.U ); + } + + public static List GetSubDivisionsV( MeshAxisSubDivider divider, Transform3D quadTransform ) + { + return GetSubDivisions( divider, quadTransform, Axis.V ); + } + + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/MeshAxisSubDivider.cs.uid b/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/MeshAxisSubDivider.cs.uid new file mode 100644 index 0000000..5213bb4 --- /dev/null +++ b/Runtime/Procedural/Baking/MultiBaker/MeshAxisSubDividers/MeshAxisSubDivider.cs.uid @@ -0,0 +1 @@ +uid://bv6l2kx1pkyf1 diff --git a/Runtime/Procedural/Baking/MultiBaker/Octahedral_Baker.cs b/Runtime/Procedural/Baking/MultiBaker/Octahedral_Baker.cs index 1a65cd1..74a4fe5 100644 --- a/Runtime/Procedural/Baking/MultiBaker/Octahedral_Baker.cs +++ b/Runtime/Procedural/Baking/MultiBaker/Octahedral_Baker.cs @@ -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( mb.X_outputMesh ); + // var material = Materials.Get( mb.X_outputMesh ); + + var material = MaterialSurfaceContainer.GetMaterialInSlot( mb.X_outputMesh, MaterialSlot.MeshSurface ); if ( material == null ) { diff --git a/Runtime/Procedural/Baking/MultiBaker/_XX_MultiBakeModeBillboardBase.cs b/Runtime/Procedural/Baking/MultiBaker/_XX_MultiBakeModeBillboardBase.cs index 3c1d003..ab41dac 100644 --- a/Runtime/Procedural/Baking/MultiBaker/_XX_MultiBakeModeBillboardBase.cs +++ b/Runtime/Procedural/Baking/MultiBaker/_XX_MultiBakeModeBillboardBase.cs @@ -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( mb.X_outputMesh ); + // var material = Materials.Get( mb.X_outputMesh ); + var material = MaterialSurfaceContainer.GetMaterialInSlot( mb.X_outputMesh, MaterialSlot.MeshSurface ); material.AlbedoTexture = _XX_BakingPass.Get( passes, BakingTargetType.Albedo, BakingTargetType.Lit ); diff --git a/Runtime/Procedural/Mesh/MaterialSurfaceContainer.cs b/Runtime/Procedural/Mesh/MaterialSurfaceContainer.cs index 803d06f..460a172 100644 --- a/Runtime/Procedural/Mesh/MaterialSurfaceContainer.cs +++ b/Runtime/Procedural/Mesh/MaterialSurfaceContainer.cs @@ -7,16 +7,18 @@ using System; namespace Rokojori { + public enum MaterialSlot + { + None, + MeshSurface, + MeshSurfaceOverride, + Override, + Overlay + } + public abstract class MaterialSurfaceContainer { - public enum MaterialSlot - { - None, - MeshSurface, - MeshSurfaceOverride, - Override, - Overlay - } + protected Node3D _owner; protected int _surfaceIndex; @@ -29,7 +31,7 @@ namespace Rokojori } public abstract MaterialSlot GetActiveMaterialSlot(); - public abstract Material GetMaterialInSlot( MaterialSlot slot ); + public abstract T GetMaterialInSlot( 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() where T:Material { - return GetMaterialInSlot( GetActiveMaterialSlot() ); + return (T)GetMaterialInSlot( 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( Node3D owner, MaterialSlot slot, int surfaceIndex = 0 ) where T:Material + { + var mc = From( owner, surfaceIndex ); + + if ( mc == null ) + { + return null; + } + + return mc.GetMaterialInSlot( 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: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( 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( 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; diff --git a/Runtime/Procedural/Mesh/MaterialSurfaceContainer.cs.uid b/Runtime/Procedural/Mesh/MaterialSurfaceContainer.cs.uid new file mode 100644 index 0000000..caf370d --- /dev/null +++ b/Runtime/Procedural/Mesh/MaterialSurfaceContainer.cs.uid @@ -0,0 +1 @@ +uid://bk3iamd4q3siu diff --git a/Runtime/Procedural/Mesh/MeshCombiner.cs b/Runtime/Procedural/Mesh/MeshCombiner.cs index a232349..d3a720f 100644 --- a/Runtime/Procedural/Mesh/MeshCombiner.cs +++ b/Runtime/Procedural/Mesh/MeshCombiner.cs @@ -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(); - } + await CombineMeshes(); + } @@ -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(); - } - - 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(); + if ( ! combineMeshes ) + { + if ( outputContainer == null ) + { + outputContainer = this.CreateChild(); + } + + 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 ( pivot != null ) + if ( combineMeshes ) { - trsf.Origin -= pivot.GlobalPosition; - } + if ( pivot != null ) + { + trsf.Origin -= pivot.GlobalPosition; + } - smg.ApplyTransform( trsf ); + smg.ApplyTransform( trsf ); + } + meshGeometry.Add( smg ); + + if ( isCombinedMaterial && ! combineMeshes ) + { + meshGeometry.GenerateMesh( Mesh.PrimitiveType.Triangles, arrayMesh ); + arrayMesh.SurfaceSetMaterial( index, usedMaterial ); + + var meshInstance = outputContainer.CreateChild(); + 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; } - meshGeometry.GenerateMesh( Mesh.PrimitiveType.Triangles, arrayMesh ); + + outputMaterials.Add( usedMaterial ); + if ( combineMeshes ) + { + meshGeometry.GenerateMesh( Mesh.PrimitiveType.Triangles, arrayMesh ); + arrayMesh.SurfaceSetMaterial( index, usedMaterial ); - arrayMesh.SurfaceSetMaterial( index, m ); - outputMaterials.Add( m ); - index ++; + index ++; + } } ); @@ -468,16 +462,19 @@ namespace Rokojori this.LogInfo( "Processing done, adding outputs", arrayMesh.GetSurfaceCount() ); - if ( outputMesh == null ) - { - this.LogInfo( "Created outputMesh"); - outputMesh = this.CreateChild(); - } - - this.outputMaterials = outputMaterials.ToArray(); - outputMesh.Mesh = arrayMesh; + if ( combineMeshes ) + { + if ( outputMesh == null ) + { + this.LogInfo( "Created outputMesh"); + outputMesh = this.CreateChild(); + } + + outputMesh.Mesh = arrayMesh; + + } return; } diff --git a/Runtime/Procedural/Mesh/MeshExtractor.cs b/Runtime/Procedural/Mesh/MeshExtractor.cs index 4e45274..631ebd9 100644 --- a/Runtime/Procedural/Mesh/MeshExtractor.cs +++ b/Runtime/Procedural/Mesh/MeshExtractor.cs @@ -158,14 +158,14 @@ namespace Rokojori return list; } - public static List> ExtractSurfaces( Node n, List> list = null, bool trackOwners = false ) + public static List> ExtractSurfaces( Node n, List> list = null ) { list = list == null ? new List>() : 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++ ) diff --git a/Runtime/Procedural/Mesh/MeshGeometry.cs b/Runtime/Procedural/Mesh/MeshGeometry.cs index bb0259a..316f910 100644 --- a/Runtime/Procedural/Mesh/MeshGeometry.cs +++ b/Runtime/Procedural/Mesh/MeshGeometry.cs @@ -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 uDivisions, List 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 + { + 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(); + uSegments.Add( 0 ); + uSegments.AddRange( uDivisions ); + uSegments.Add( 1 ); + + var vSegments = new List(); + 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; diff --git a/Runtime/Procedural/Mesh/VertexAttributes.cs b/Runtime/Procedural/Mesh/VertexAttributes.cs new file mode 100644 index 0000000..42b18d2 --- /dev/null +++ b/Runtime/Procedural/Mesh/VertexAttributes.cs @@ -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; + + } + } +} \ No newline at end of file diff --git a/Runtime/Procedural/Mesh/VertexAttributes.cs.uid b/Runtime/Procedural/Mesh/VertexAttributes.cs.uid new file mode 100644 index 0000000..0bc30b7 --- /dev/null +++ b/Runtime/Procedural/Mesh/VertexAttributes.cs.uid @@ -0,0 +1 @@ +uid://sskx2gnmrilv diff --git a/Runtime/Procedural/Points/PointData.cs b/Runtime/Procedural/Points/PointData.cs index 110dc21..4ac00ee 100644 --- a/Runtime/Procedural/Points/PointData.cs +++ b/Runtime/Procedural/Points/PointData.cs @@ -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; diff --git a/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBuffer.cs b/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBuffer.cs index 2b6455c..285431e 100644 --- a/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBuffer.cs +++ b/Runtime/Procedural/Textures/TextureCombiner/TextureCombinerBuffer.cs @@ -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 ); } diff --git a/Runtime/Shading/Library/Quaternion.gdshaderinc b/Runtime/Shading/Library/Quaternion.gdshaderinc new file mode 100644 index 0000000..d53a2b8 --- /dev/null +++ b/Runtime/Shading/Library/Quaternion.gdshaderinc @@ -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; +} \ No newline at end of file diff --git a/Runtime/Shading/Library/Quaternion.gdshaderinc.uid b/Runtime/Shading/Library/Quaternion.gdshaderinc.uid new file mode 100644 index 0000000..a0f17ac --- /dev/null +++ b/Runtime/Shading/Library/Quaternion.gdshaderinc.uid @@ -0,0 +1 @@ +uid://c6trfbv30psqx diff --git a/Runtime/Shading/Library/Transform.gdshaderinc b/Runtime/Shading/Library/Transform.gdshaderinc index 079ad19..9e38c1f 100644 --- a/Runtime/Shading/Library/Transform.gdshaderinc +++ b/Runtime/Shading/Library/Transform.gdshaderinc @@ -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 ); } \ No newline at end of file diff --git a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/MouseEditorCamera Default Inputs.tres b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/MouseEditorCamera Default Inputs.tres index 007ca30..888d1f6 100644 --- a/Runtime/VirtualCameras/MouseEditorCamera/Inputs/MouseEditorCamera Default Inputs.tres +++ b/Runtime/VirtualCameras/MouseEditorCamera/Inputs/MouseEditorCamera Default Inputs.tres @@ -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