lambdacube-engine-0.2.1: Graphics/LambdaCube/Mesh.hs
module Graphics.LambdaCube.Mesh where
import Data.Maybe
import Foreign
import Foreign.C.Types
import qualified Data.IntMap as IntMap
import Unsafe.Coerce -- because realToFrac just doesn't cut it...
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 -- ^ The render operation type used to render this submesh
, smVertexData :: Maybe (VertexData vb) -- ^ Indicates if this submesh shares vertex data with other meshes or whether it has it's own vertices.
, smIndexData :: Maybe (IndexData ib) -- ^ Face index data
-- , smExtremityPoints :: [FloatType3]
, smMaterialName :: String -- ^ Name of the material this SubMesh uses.
}
data (HardwareVertexBuffer vb, HardwareIndexBuffer ib) => Mesh vb ib
= Mesh
{ msSubMeshList :: [SubMesh vb ib]
-- , msSubMeshNameMap :: Map String Int
, msBoundRadius :: FloatType
-- , msSkeletonName :: String
-- , msVertexBufferUsage :: Usage
-- , msIndexBufferUsage :: Usage
-- , msVertexBufferShadowBuffer :: Bool
-- , msIndexBufferShadowBuffer :: Bool
, msSharedVertexData :: Maybe (VertexData vb)
}
-- TODO
calculateBoundingRadius :: (HardwareVertexBuffer vb, HardwareIndexBuffer ib) => Mesh vb ib -> IO FloatType
calculateBoundingRadius mesh = do
let processSubMesh r sm = do
-- get pointer to position vertex attribute container array
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)
-- lock vb and ib for reading
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
-- pass through buffer and process triangles
d <- foldM' getVertexDistance r [0..getNumVertices vb-1]
unlock vb
return d
foldM' processSubMesh 0 $ msSubMeshList mesh