|
|
@ -135,33 +135,39 @@ void main() { |
|
|
|
public int GetUniformLocation(string name) { |
|
|
|
return GL.GetUniformLocation(Handle, name); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// FIXME: this should probably be IDisposable?
|
|
|
|
public class Photo { |
|
|
|
private string file; |
|
|
|
private Texture texture; |
|
|
|
private Texture placeholder; |
|
|
|
private Image<Rgba32> image; |
|
|
|
private Image<Rgba32>? image = null; |
|
|
|
|
|
|
|
public Photo(Image<Rgba32> image, Texture placeholder) { |
|
|
|
this.image = image; |
|
|
|
public Photo(string file, Texture placeholder) { |
|
|
|
this.file = file; |
|
|
|
this.placeholder = placeholder; |
|
|
|
texture = placeholder; |
|
|
|
} |
|
|
|
|
|
|
|
public async void Load() { |
|
|
|
image = await Image.LoadAsync<Rgba32>(file); |
|
|
|
ExifProfile? exifs = image.Metadata.ExifProfile; |
|
|
|
if (exifs != null) { |
|
|
|
foreach (IExifValue exif in exifs.Values) { |
|
|
|
if (exif.Tag.ToString() == "Model") { |
|
|
|
Console.WriteLine($"{exif.Tag}: {exif.GetValue()}"); |
|
|
|
Console.WriteLine($"{file} {exif.Tag}: {exif.GetValue()}"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public Texture Texture() { |
|
|
|
if (texture == placeholder) { |
|
|
|
if (texture == placeholder && image != null) { |
|
|
|
Console.WriteLine("making texture for " + file); |
|
|
|
texture = new Texture(image); |
|
|
|
image.Dispose(); |
|
|
|
image = null; |
|
|
|
} |
|
|
|
return texture; |
|
|
|
} |
|
|
@ -177,6 +183,7 @@ public class Texture : IDisposable { |
|
|
|
image.CopyPixelDataTo(pixelBytes); |
|
|
|
|
|
|
|
Handle = GL.GenTexture(); |
|
|
|
Console.WriteLine("GL.GenTexture #" + Handle); |
|
|
|
GL.ActiveTexture(TextureUnit.Texture0); |
|
|
|
GL.BindTexture(TextureTarget.Texture2D, Handle); |
|
|
|
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, Size.X, Size.Y, 0, PixelFormat.Rgba, PixelType.UnsignedByte, pixelBytes); |
|
|
@ -223,7 +230,7 @@ public class UiGeometry { |
|
|
|
public UiGeometry(Vector2i windowSize) { |
|
|
|
WindowSize = windowSize; |
|
|
|
|
|
|
|
int numThumbnails = 20; |
|
|
|
int numThumbnails = 10; |
|
|
|
int thumbnailHeight = WindowSize.Y / numThumbnails; |
|
|
|
int thumbnailWidth = (int) 1.0 * thumbnailHeight * activeCamera.Resolution.X / activeCamera.Resolution.Y; |
|
|
|
for (int i = 0; i < numThumbnails; i++) { |
|
|
@ -261,7 +268,6 @@ public class Game : GameWindow { |
|
|
|
1, 2, 3 // second triangle
|
|
|
|
}; |
|
|
|
|
|
|
|
bool doneLoading = false; |
|
|
|
int VertexBufferObject; |
|
|
|
int ElementBufferObject; |
|
|
|
int VertexArrayObject; |
|
|
@ -355,22 +361,15 @@ public class Game : GameWindow { |
|
|
|
string[] files = Directory.GetFiles(@"c:\users\colin\pictures\photos\2023\07\14\"); |
|
|
|
//string[] files = Directory.GetFiles(@"C:\Users\colin\Pictures\photos\2018\06\23");
|
|
|
|
|
|
|
|
List<Task<Image<Rgba32>>> imageTasks = new(); |
|
|
|
for (int i = 0; i < files.Count(); i++) { |
|
|
|
string file = files[i]; |
|
|
|
if (file.ToLower().EndsWith(".jpg")) { |
|
|
|
imageTasks.Add(Image.LoadAsync<Rgba32>(file)); |
|
|
|
Photo photo = new Photo(file, TEXTURE_WHITE); |
|
|
|
photos.Add(photo); |
|
|
|
await Task.Run( () => { photo.Load(); }); |
|
|
|
Console.WriteLine("file " + i); |
|
|
|
} |
|
|
|
} |
|
|
|
Console.WriteLine(DateTime.Now); |
|
|
|
await Task.WhenAll(imageTasks); |
|
|
|
Console.WriteLine(DateTime.Now); |
|
|
|
|
|
|
|
foreach (Task<Image<Rgba32>> task in imageTasks) { |
|
|
|
Photo photo = new(task.Result, TEXTURE_WHITE); |
|
|
|
photos.Add(photo); |
|
|
|
} |
|
|
|
doneLoading = true; |
|
|
|
} |
|
|
|
|
|
|
|
protected override void OnUnload() { |
|
|
@ -379,9 +378,6 @@ public class Game : GameWindow { |
|
|
|
|
|
|
|
protected override void OnRenderFrame(FrameEventArgs e) { |
|
|
|
base.OnRenderFrame(e); |
|
|
|
if (!doneLoading) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
GL.Clear(ClearBufferMask.ColorBufferBit); |
|
|
|
GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBufferObject); |
|
|
|