rj-action-library/Runtime/Procedural/Baking/PointMesh/PointMeshBaker.cs

86 lines
2.0 KiB
C#

using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class PointMeshBaker:Node
{
[Export]
public Texture2D albedo;
[Export]
public Texture2D normal;
[Export]
public MeshInstance3D output;
[Export]
public int pixelsX;
[Export]
public int pixelsY;
[Export]
public Vector2 pivot;
[Export]
public Vector3 offset;
[Export]
public Vector3 scale;
[ExportToolButton( "Bake")]
public Callable BakeButton => Callable.From( () =>
{
BakePointMesh();
}
);
public void BakePointMesh()
{
var mg = new MeshGeometry( true, false, true, false );
mg.customMeshAttributes.Add( new MeshAttributeVector4List( 0 ) );
mg.normals = null;
var albedoImage = albedo.GetImage();
var normalImage = normal.GetImage();
var index = 0;
for ( int x = 0; x < pixelsX; x++ )
{
for ( int y = 0; y < pixelsY; y++ )
{
var fx = x / (float) pixelsX;
var fy = 1f - y / (float) pixelsY;
var position = new Vector3( fx - pivot.X, fy - pivot.Y, 0 ) * scale + offset;
var colorPosX = Mathf.FloorToInt( fx * albedoImage.GetSize().X );
var colorPosY = Mathf.FloorToInt( fy * albedoImage.GetSize().Y );
var color = albedoImage.GetPixel( colorPosX, colorPosY );
var normalPosX = Mathf.FloorToInt( fx * normalImage.GetSize().X );
var normalPosY = Mathf.FloorToInt( fy * normalImage.GetSize().Y );
var normal = normalImage.GetPixel( normalPosX, normalPosY );
mg.AddPoint( position, color.SRGBtoLinear(), normal.SRGBtoLinear().ToVector3() * 2.0f - Vector3.One, 0 );
// this.LogInfo( "Created point at:", index, position );
index ++;
}
}
output = output == null ? this.CreateChild<MeshInstance3D>() : output;
output.Mesh = mg.GenerateMesh( Mesh.PrimitiveType.Points, null, false );
}
}
}