packages feed

3dmodels-0.3.0: Graphics/Model/MikuMikuDance/Types.hs

module Graphics.Model.MikuMikuDance.Types (
  VertexIx,
  TexIx,
  BoneIx,
  MorphIx,
  MaterialIx,
  BodyIx,
  MMD(..),
  MMDVertex(..),
  MMDWeight(..),
  MMDMaterial(..),
  MMDBone(..),
  MMDIK(..),
  MMDMorph(..),
  MMDMorphOffest(..),
  MMDGroup(..),
  MMDRigidBody(..),
  MMDJoint(..),
  MMDSoftBody(..),

  VMD(..),
  BoneKeyframe(..),
  MorphKeyframe(..),
  CameraKeyframe(..),
  LightKeyframe(..),
  ShadowKeyframe(..),
  ControlKeyframe(..),

  VPD
  ) where
import qualified Data.ByteString as B
import Data.Int
import Data.Word
import Linear


-- * PMX (Polygon Model eXtended)

type VertexIx = Int32
type TexIx = Int32
type BoneIx = Int32
type MorphIx = Int32
type MaterialIx = Int32
type BodyIx = Int32

-- | PMX 2.1 spec made by Kyockhook-P (極北P)
data MMD = MMD
	{ mmdFormat :: Float
	-- ^ 1.0: PMD, 2.0/2.1:PMX
	, mmdCharCode :: String
	-- ^ UTF-16, UTF-8, Shift-JIS
	, mmdExtUVs :: Word8 -- ^ in [0..4]
	, mmdNameJa :: B.ByteString
	, mmdName :: B.ByteString
	, mmdCommentJa :: B.ByteString
	, mmdComment :: B.ByteString
	, mmdVertices :: [MMDVertex]
	, mmdPlanes :: [V3 VertexIx]
	-- ^ ABC(Triangle), /Since 2.1/: AAA(Point), ABA(Line)
	, mmdTextures :: [B.ByteString]
	, mmdAltToonTex :: [B.ByteString]
	-- ^ length: 0(PMX) or 10(PMD, if exists)
	, mmdMaterials :: [MMDMaterial]
	, mmdBones :: [MMDBone]
	, mmdMorphs :: [MMDMorph]
	, mmdGroups :: [MMDGroup]
	, mmdRigidBodies :: [MMDRigidBody]
	, mmdJoints :: [MMDJoint]
	, mmdSoftBodies :: [MMDSoftBody]
	-- ^ /Since 2.1/
	} deriving Show

data MMDVertex = MMDVertex
	{ vPosition :: V3 Float
	, vNormal :: V3 Float
	, vUV :: V2 Float
	, vExtUVs :: [V4 Float]
	, vWeight :: MMDWeight
	, vEdgeScale :: Float
	} deriving Show

data MMDWeight =
	  BDEF1 BoneIx
	-- | Weight of the first bone
	| BDEF2 (V2 BoneIx) Float
	-- | Weight of each bone
	| BDEF4 (V4 BoneIx) (V4 Float)
	-- | BDEF2 + SDEF-C(x,y,z) + SDEF-R0(x,y,z) + SDEF-R1(x,y,z)
	| SDEF (V2 BoneIx) Float (M33 Float)
	-- | /Since 2.1/ DualQuaternion
	| QDEF (V4 BoneIx) (V4 Float)
	deriving Show

data MMDMaterial = MMDMaterial
	{ mNameJa :: B.ByteString
	, mName :: B.ByteString
	, mDiffuse :: V4 Float -- ^ RGBA
	, mSpecular :: V3 Float -- ^ RGB
	, mSpecularFactor :: Float
	, mAmbient :: V3 Float -- ^ RGB
	-- | 1:cullface=both, 2:drop shadow, 4:render to self shadow map,
	-- 8:render to self shadow, 16:draw edges,
	-- /Since 2.1/ => 32:vertex color, 64:As Points, 128:As Lines
	, mOptions :: Word8
	, mEdgeColor :: V4 Float -- ^ RGBA
	-- | /Since 2.1/ Point size (See mOptions)
	, mEdgeSize :: Float
	, mTexture :: TexIx
	, mSphereTexture :: TexIx
	-- | 0: None, 1: Multiply, 2: Add, 3: Use subtexture
	, mSphereMode :: Word8
	-- | Indexed texture >= 0, -10 <= shered toon texture (0-9) - 10 < 0
	, mToonTexture :: TexIx
	, mComment :: B.ByteString
	-- | The number of planes * 3
	, mNumVertices :: Word32
	} deriving Show

data MMDBone = MMDBone
	{ bNameJa :: B.ByteString
	, bName :: B.ByteString
	, bPosition :: V3 Float
	, bParent :: BoneIx
	, bTransformDepth :: Int
	, bFlags :: Word16
	, bLInk :: Either (V3 Float) BoneIx -- ^ offset or bone index
	, bFollow :: Maybe (BoneIx, Float)
	, bAxis :: Maybe (V3 Float)
	, bLocalAxis :: Maybe (V3 Float, V3 Float)
	, bExternalParent :: Maybe Int
	, bIK :: Maybe MMDIK
	} deriving Show

data MMDIK = MMDIK
	{ ikTarget :: BoneIx
	, ikLoopCount :: Int
	, ikRotLimitPerLoop :: Float
	, ikLinks :: [(BoneIx, Maybe (V3 Float, V3 Float))]
	} deriving Show

data MMDMorph = MMDMorph
	{ mphNameJa :: B.ByteString
	, mphName :: B.ByteString
	, mphUICtrl :: Word8
	, mphOffsets :: [MMDMorphOffest]
	} deriving Show

data MMDMorphOffest =
	  GroupMorph MorphIx Float
	| VertexMorph VertexIx (V3 Float) -- ^ offset
	| BoneMorph BoneIx (V3 Float) (V4 Float)
	| UVMorph VertexIx (V4 Float)
	| UV1Morph VertexIx (V4 Float)
	| UV2Morph VertexIx (V4 Float)
	| UV3Morph VertexIx (V4 Float)
	| UV4Morph VertexIx (V4 Float)
	| MaterialMorph MaterialIx Word8 (V4 Float) (V3 Float) Float (V3 Float) (V4 Float) Float (V4 Float) (V4 Float) (V4 Float)
	-- ^ 0:*, 1:+. Diffuse, Specular, SpecularFactor, Ambient, EdgeColor, EdgeSize, TextureFactors, SphereTexFactors, ToonTexFactors.
	| FlipMorph MorphIx Float
	-- ^ /Since 2.1/
	| ImpulseMorph BodyIx Bool (V3 Float) (V3 Float)
	-- ^ /Since 2.1/ isLocal, velocity, torque
	deriving Show

data MMDGroup = MMDGroup
	{ gNameJa :: B.ByteString
	, gName :: B.ByteString
	, gIsReserved :: Bool
	, gElements :: [Either BoneIx MorphIx]
	} deriving Show

data MMDRigidBody = MMDRigidBody
	{ rbNameJa :: B.ByteString
	, rbName :: B.ByteString
	, rbRelated :: BoneIx
	, rbGroup :: Word8
	, rbNoCollisionGroup :: Word16
	, rbShape :: Word8 -- ^ 0:Ball, 1:Box, 2:Capsule
	, rbSize :: V3 Float -- ^ (x,y,z)
	, rbPosition :: V3 Float -- ^ (x,y,z)
	, rbRotation :: V3 Float -- ^ (x,y,z)
	, rbMass :: Float
	, rbSpeedAttenuation :: Float
	, rbRotAttenuation :: Float
	, rbRepulsion :: Float
	, rbFriction :: Float
	, rbComputeMode :: Word8 -- ^ 0: static, 1: dynamic, 2: both
	} deriving Show

data MMDJoint = MMDJoint
	{ jNameJa :: B.ByteString
	, jName :: B.ByteString
	, jointType :: Word8
	, jBone1 :: BodyIx
	, jBone2 :: BodyIx
	, jPosition :: V3 Float
	, jRotation :: V3 Float
	, jPosUpperBound :: V3 Float
	, jPosLowerBound :: V3 Float
	, jRotUpperBound :: V3 Float
	, jRotLowerBound :: V3 Float
	, jPosSpringConst :: V3 Float
	, jRotSpringConst :: V3 Float
	} deriving Show

-- | /Since 2.1/
data MMDSoftBody = MMDSoftBody
	{ sbNameJa :: B.ByteString
	, sbName :: B.ByteString
	, sbShape :: Word8
	-- ^ 0:TriMesh, 1:Rope
	, sbRelated :: MaterialIx
	, sbGroup :: Word8
	, sbNoCollisionGroup :: Word16
	, sbOptions :: Word8
	-- ^ 1:generateBendingConstraints(B-Link), 2:generateClusters, 4:randomizeConstraints
	, sbBLinkDistance :: Int
	, sbNumClusters :: Int
	, sbMass :: Float
	, sbCollisionMargin :: Float
	, sbAeroModel :: Int
	-- ^ 0:V_Point, 1:V_TwoSided, 2:V_OneSided, 3:F_TwoSided, 4:F_OneSided
	, sbConfig :: V3 (V4 Float)
	-- ^ (VCF DP DG LF, PR VC DF MT, CHR KHR SHR AHR)
	, sbCluster :: V2 (V3 Float)
	-- ^ (SRHR_CL SKHR_CL SSHR_CL, SR_SPLT_CL SK_SPLT_CL SS_SPLT_CL)
	, sbIteration :: V4 Int
	-- ^ V_IT P_IT D_IT C_IT
	, sbMaterial :: V3 Float
	-- ^ LST AST VST
	, sbAnchorRigidBodies :: [(BodyIx, VertexIx, Bool)]
	-- ^ True: Enable Near mode
	, sbPinVertices :: [VertexIx]
	} deriving Show


-- * VMD (Vocaloid Motion Data)

-- VMD strings are encoded in CP932
-- | Vocaloid Motion Data
data VMD = VMD
	{ vmdModelName :: B.ByteString -- ^ CP932
	, boneMotion :: [BoneKeyframe]
	, morphMotion :: [MorphKeyframe]
	, cameraMotion :: [CameraKeyframe]
	, lightMotion :: [LightKeyframe]
	, shadowMotion :: [ShadowKeyframe]
	, controlMotion :: [ControlKeyframe]
	} deriving Show

data BoneKeyframe = BoneKeyframe
	{ bkName :: B.ByteString
	, bkFrame :: Word32
	, bkPosition :: V3 Float -- ^ XYZ or (0,0,0)
	, bkRotation :: V4 Float -- ^ Quaternion XYZW or (0,0,0,1)
	, bkInterpolation :: [Int] -- XXX description
	} deriving Show

data MorphKeyframe = MorphKeyframe
	{ moName :: B.ByteString
	, moFrame :: Word32
	, moFace :: Float
	} deriving Show

data CameraKeyframe = CameraKeyframe
	{ ckFrame :: Word32
	, ckDistance :: Float
	, ckPosition :: V3 Float
	, ckRotation :: V3 Float
	, ckBezier :: [Int] -- ^ bezier int[24]
	, ckViewingAngle :: Word32 -- ^ in degree
	, ckPerspective :: Bool -- 0:Enable, 1:Disable
	} deriving Show

data LightKeyframe = LightKeyframe
	{ lkFrame :: Word32
	, lkColor :: V3 Float
	, lkPosition :: V3 Float
	} deriving Show

data ShadowKeyframe = ShadowKeyframe
	{ skFrame :: Word32
	, skType :: Int
	, skDistance :: Float -- ^ 0.1 - (dist * 0.00001)
	} deriving Show

data ControlKeyframe = ControlKeyframe
	{ ctFrame :: Word32
	, ctModelVisibility :: Bool
	, ctIKCapability :: [(B.ByteString, Bool)]
	} deriving Show


-- * VPD

-- | Vocaloid Pose Data
-- (name of a Bone, position of the bone, quaternion of the bone)
type VPD = (B.ByteString, V3 Float, V4 Float)


-- * VAC

-- | Vocaloid Accessory 
-- (name of an accessory, .x filename, position, eular angle, name of the bound bone)
type VAC = (String, FilePath, Float, V3 Float, V3 Float, String)