module Graphics.LambdaCube.Mesh where
import Data.Maybe
import Foreign
import Foreign.C.Types
import qualified Data.IntMap as IntMap
import Unsafe.Coerce
import Graphics.LambdaCube.HardwareBuffer
import Graphics.LambdaCube.HardwareIndexBuffer
import Graphics.LambdaCube.HardwareVertexBuffer
import Graphics.LambdaCube.RenderOperation
import Graphics.LambdaCube.Types
import Graphics.LambdaCube.Utility
import Graphics.LambdaCube.VertexIndexData
data (HardwareVertexBuffer vb, HardwareIndexBuffer ib) => SubMesh vb ib
= SubMesh
{ smOperationType :: OperationType
, smVertexData :: Maybe (VertexData vb)
, smIndexData :: Maybe (IndexData ib)
, smMaterialName :: String
}
data (HardwareVertexBuffer vb, HardwareIndexBuffer ib) => Mesh vb ib
= Mesh
{ msSubMeshList :: [SubMesh vb ib]
, msBoundRadius :: FloatType
, msSharedVertexData :: Maybe (VertexData vb)
}
calculateBoundingRadius :: (HardwareVertexBuffer vb, HardwareIndexBuffer ib) => Mesh vb ib -> IO FloatType
calculateBoundingRadius mesh = do
let processSubMesh r sm = do
let Just vd = if isNothing (smVertexData sm) then msSharedVertexData mesh else smVertexData sm
posve = head $ filter ((VES_POSITION ==) . veSemantic) $ vdElementList $ vdVertexDeclaration vd
vb = (vbbBindingMap $ vdVertexBufferBinding vd) IntMap.! (veSource posve)
offs = veOffset posve
stride = getVertexSize vb
pb <- lock vb offs (getSizeInBytes vb offs) HBL_READ_ONLY
let getVertexDistance l i = do
let p :: Ptr CFloat
p = plusPtr pb $ i * stride
f = unsafeCoerce :: CFloat -> Float
[x,y,z] <- peekArray 3 p
return $ max l $ f $ sqrt $ x*x + y*y + z*z
d <- foldM' getVertexDistance r [0..getNumVertices vb1]
unlock vb
return d
foldM' processSubMesh 0 $ msSubMeshList mesh