never executed always true always false
    1 {-|
    2 Module: Flaw.Visual.Geometry.Vertex
    3 Description: Useful vertex structures with support for Collada.
    4 License: MIT
    5 -}
    6 
    7 {-# LANGUAGE RankNTypes, StandaloneDeriving, TemplateHaskell #-}
    8 
    9 module Flaw.Visual.Geometry.Vertex
   10   (
   11   -- * Attributes
   12     HasPositionAttribute(..)
   13   , HasNormalAttribute(..)
   14   , HasTexcoordAttribute(..)
   15   , HasWeightsBonesAttributes(..)
   16   , vertexAttribute
   17   -- * Predefined vertices
   18   , QuadVertex(..)
   19   -- ** Predefined Collada vertices
   20   , ColladaVertex(..)
   21   , VertexP(..)
   22   , VertexPN(..)
   23   , VertexPT(..)
   24   , VertexPNT(..)
   25   , VertexPNTWB(..)
   26   ) where
   27 
   28 import qualified Data.Vector.Generic as VG
   29 import qualified Data.Vector.Storable as VS
   30 import Foreign.Storable
   31 
   32 import Flaw.Asset.Collada
   33 import Flaw.FFI
   34 import Flaw.Graphics.Program
   35 import Flaw.Math
   36 
   37 class HasPositionAttribute v where
   38   -- | Get offset and format of position attribute.
   39   vertexPositionAttribute :: v -> (Int, AttributeFormat Float3)
   40 
   41 class HasNormalAttribute v where
   42   -- | Get offset and format of normal attribute.
   43   vertexNormalAttribute :: v -> (Int, AttributeFormat Float3)
   44 
   45 class HasTexcoordAttribute v where
   46   -- | Get offset and format of texcoord attribute.
   47   vertexTexcoordAttribute :: v -> (Int, AttributeFormat Float2)
   48 
   49 -- | Class of vertex having 4 bones and weights for skeletal animation.
   50 class HasWeightsBonesAttributes v where
   51   -- | Get offset and format of weights attribute.
   52   vertexWeightsAttribute :: v -> (Int, AttributeFormat Float4)
   53   -- | Get offset and format of bones attribute.
   54   vertexBonesAttribute :: v -> (Int, AttributeFormat Word32_4)
   55 
   56 -- | Create attribute from pair (offset, format) provided with slot and divisor.
   57 vertexAttribute :: OfAttributeType a => Int -> Int -> (Int, AttributeFormat a) -> Program (Node a)
   58 vertexAttribute slot divisor (offset, format) = attribute slot offset divisor format
   59 
   60 genStruct "QuadVertex"
   61   [ ([t| Float4 |], "position")
   62   ]
   63 
   64 class Storable q => ColladaVertex q where
   65   createColladaVertices :: ColladaVerticesData -> ColladaM (VS.Vector q)
   66 
   67 -- | Replace empty vector with sequence of fallback values.
   68 fallbackVertexData :: VG.Vector v a => Int -> a -> v a -> v a
   69 fallbackVertexData count fallbackValue inputVector = if VG.null inputVector then VG.replicate count fallbackValue else inputVector
   70 
   71 genStruct "VertexP"
   72   [ ([t| Float3 |], "position")
   73   ]
   74 
   75 deriving instance Eq VertexP
   76 deriving instance Ord VertexP
   77 
   78 instance HasPositionAttribute VertexP where
   79   vertexPositionAttribute _ = (0, AttributeVec3 AttributeFloat32)
   80 
   81 instance ColladaVertex VertexP where
   82   createColladaVertices verticesData@ColladaVerticesData
   83     { cvdCount = count
   84     } = do
   85     positions <- cvdPositions verticesData
   86     return $ VG.generate count $ \i -> VertexP
   87       { f_VertexP_position = positions VG.! i
   88       }
   89 
   90 genStruct "VertexPN"
   91   [ ([t| Float3 |], "position")
   92   , ([t| Float3 |], "normal")
   93   ]
   94 
   95 deriving instance Eq VertexPN
   96 deriving instance Ord VertexPN
   97 
   98 instance HasPositionAttribute VertexPN where
   99   vertexPositionAttribute _ = (0, AttributeVec3 AttributeFloat32)
  100 
  101 instance HasNormalAttribute VertexPN where
  102   vertexNormalAttribute _ = (12, AttributeVec3 AttributeFloat32)
  103 
  104 instance ColladaVertex VertexPN where
  105   createColladaVertices verticesData@ColladaVerticesData
  106     { cvdCount = count
  107     } = do
  108     positions <- cvdPositions verticesData
  109     normals <- cvdNormals verticesData
  110     return $ VG.generate count $ \i -> VertexPN
  111       { f_VertexPN_position = positions VG.! i
  112       , f_VertexPN_normal = normals VG.! i
  113       }
  114 
  115 genStruct "VertexPT"
  116   [ ([t| Float3 |], "position")
  117   , ([t| Float2 |], "texcoord")
  118   ]
  119 
  120 deriving instance Eq VertexPT
  121 deriving instance Ord VertexPT
  122 
  123 instance HasPositionAttribute VertexPT where
  124   vertexPositionAttribute _ = (0, AttributeVec3 AttributeFloat32)
  125 
  126 instance HasTexcoordAttribute VertexPT where
  127   vertexTexcoordAttribute _ = (12, AttributeVec2 AttributeFloat32)
  128 
  129 instance ColladaVertex VertexPT where
  130   createColladaVertices verticesData@ColladaVerticesData
  131     { cvdCount = count
  132     } = do
  133     positions <- cvdPositions verticesData
  134     texcoords <- fallbackVertexData count (Vec2 0 0) <$> cvdTexcoords verticesData
  135     return $ VG.generate count $ \i -> VertexPT
  136       { f_VertexPT_position = positions VG.! i
  137       , f_VertexPT_texcoord = let Vec2 tx ty = texcoords VG.! i in Vec2 tx (1 - ty)
  138       }
  139 
  140 genStruct "VertexPNT"
  141   [ ([t| Float3 |], "position")
  142   , ([t| Float3 |], "normal")
  143   , ([t| Float2 |], "texcoord")
  144   ]
  145 
  146 deriving instance Eq VertexPNT
  147 deriving instance Ord VertexPNT
  148 
  149 instance HasPositionAttribute VertexPNT where
  150   vertexPositionAttribute _ = (0, AttributeVec3 AttributeFloat32)
  151 
  152 instance HasNormalAttribute VertexPNT where
  153   vertexNormalAttribute _ = (12, AttributeVec3 AttributeFloat32)
  154 
  155 instance HasTexcoordAttribute VertexPNT where
  156   vertexTexcoordAttribute _ = (24, AttributeVec2 AttributeFloat32)
  157 
  158 instance ColladaVertex VertexPNT where
  159   createColladaVertices verticesData@ColladaVerticesData
  160     { cvdCount = count
  161     } = do
  162     positions <- cvdPositions verticesData
  163     normals <- cvdNormals verticesData
  164     texcoords <- fallbackVertexData count (Vec2 0 0) <$> cvdTexcoords verticesData
  165     return $ VG.generate count $ \i -> VertexPNT
  166       { f_VertexPNT_position = positions VG.! i
  167       , f_VertexPNT_normal = normals VG.! i
  168       , f_VertexPNT_texcoord = let Vec2 tx ty = texcoords VG.! i in Vec2 tx (1 - ty)
  169       }
  170 
  171 genStruct "VertexPNTWB"
  172   [ ([t| Float3 |], "position")
  173   , ([t| Float3 |], "normal")
  174   , ([t| Float2 |], "texcoord")
  175   , ([t| Float4 |], "weights")
  176   , ([t| Word8_4 |], "bones")
  177   ]
  178 
  179 deriving instance Eq VertexPNTWB
  180 deriving instance Ord VertexPNTWB
  181 
  182 instance HasPositionAttribute VertexPNTWB where
  183   vertexPositionAttribute _ = (0, AttributeVec3 AttributeFloat32)
  184 
  185 instance HasNormalAttribute VertexPNTWB where
  186   vertexNormalAttribute _ = (12, AttributeVec3 AttributeFloat32)
  187 
  188 instance HasTexcoordAttribute VertexPNTWB where
  189   vertexTexcoordAttribute _ = (24, AttributeVec2 AttributeFloat32)
  190 
  191 instance HasWeightsBonesAttributes VertexPNTWB where
  192   vertexWeightsAttribute _ = (32, AttributeVec4 AttributeFloat32)
  193   vertexBonesAttribute _ = (48, AttributeVec4 AttributeUint8)
  194 
  195 instance ColladaVertex VertexPNTWB where
  196   createColladaVertices verticesData@ColladaVerticesData
  197     { cvdCount = count
  198     } = do
  199     positions <- cvdPositions verticesData
  200     normals <- cvdNormals verticesData
  201     texcoords <- fallbackVertexData count (Vec2 0 0) <$> cvdTexcoords verticesData
  202     bones <- cvdBones verticesData
  203     weights <- cvdWeights verticesData
  204     return $ VG.generate count $ \i -> VertexPNTWB
  205       { f_VertexPNTWB_position = positions VG.! i
  206       , f_VertexPNTWB_normal = normals VG.! i
  207       , f_VertexPNTWB_texcoord = let Vec2 tx ty = texcoords VG.! i in Vec2 tx (1 - ty)
  208       , f_VertexPNTWB_bones = bones VG.! i
  209       , f_VertexPNTWB_weights = weights VG.! i
  210       }