{-# OPTIONS_GHC -fplugin Foreign.Storable.Generic.Plugin #-}

module Render.Lit.Material.Model
  ( Model
  , VertexAttrs(..)
  , vkVertexAttrs

  , InstanceAttrs
  -- , InstanceBuffers(..)

  -- , TextureParams(..)
  -- , vkInstanceTexture

  -- , allocateInstancesWith
  , Transform
  , Material
  ) where

import RIO

import Foreign (Storable(..))
import Geomancy (Transform, Vec2)
import Geomancy.Vec3 qualified as Vec3
import Vulkan.Core10 qualified as Vk

import Resource.Model qualified as Model
import Render.Lit.Material (Material)

type Model buf = Model.Indexed buf Vec3.Packed VertexAttrs

data VertexAttrs = VertexAttrs
  { vaTexCoord0 :: Vec2
  , vaTexCoord1 :: Vec2
  , vaNormal    :: Vec3.Packed
  , vaTangent   :: Vec3.Packed
  , vaMaterial  :: Word32
  }
  deriving (Eq, Ord, Show, Generic)

instance Storable VertexAttrs where
  alignment ~_ = 4

  sizeOf ~_ = 8 + 8 + 12 + 12 + 4

  peek ptr = do
    vaTexCoord0 <- peekByteOff ptr 0
    vaTexCoord1 <- peekByteOff ptr 8
    vaNormal    <- peekByteOff ptr 16
    vaTangent   <- peekByteOff ptr 28
    vaMaterial  <- peekByteOff ptr 40
    pure VertexAttrs{..}

  poke ptr VertexAttrs{..} = do
    pokeByteOff ptr  0 vaTexCoord0
    pokeByteOff ptr  8 vaTexCoord1
    pokeByteOff ptr 16 vaNormal
    pokeByteOff ptr 28 vaTangent
    pokeByteOff ptr 40 vaMaterial

vkVertexAttrs :: [Vk.Format]
vkVertexAttrs =
  [ Vk.FORMAT_R32G32_SFLOAT    -- vTexCoord0 :: vec2
  , Vk.FORMAT_R32G32_SFLOAT    -- vTexCoord1 :: vec2
  , Vk.FORMAT_R32G32B32_SFLOAT -- vNormal    :: vec3
  , Vk.FORMAT_R32G32B32_SFLOAT -- vTangent   :: vec3
  , Vk.FORMAT_R32_UINT         -- vMaterial  :: uint
  ]

type InstanceAttrs = Transform
