0001: // ---------------------------------------------------------------------------- 0002: // 0003: // CSkinModel.cpp - スキンメッシュ管理クラス 0004: // 0005: // Copyright (c) 2002 imagire (imagire@gmail.com) 0006: // All Rights Reserved. 0007: // 0008: // ---------------------------------------------------------------------------- 0009: #define STRICT 0010: 0011: #include <windows.h> 0012: #include <mmsystem.h> 0013: #include <objbase.h> 0014: #include <malloc.h> 0015: #include <stdio.h> 0016: #include <d3d8.h> 0017: #include <d3dx8.h> 0018: #include "rmxfguid.h" 0019: #include "rmxftmpl.h" 0020: 0021: 0022: #include <d3dx8.h> 0023: #include "CSkinModel.h" 0024: 0025: //----------------------------------------------------------------------------- 0026: // 簡易マクロ 0027: //----------------------------------------------------------------------------- 0028: #define RELEASE(o) if (o){(o)->Release();(o)=NULL;} 0029: #define DELETES(o) if (o){delete[] (o);(o)=NULL;} 0030: 0031: // ---------------------------------------------------------------------------- 0032: // シェーダー 0033: // ---------------------------------------------------------------------------- 0034: // v0 = 頂点の位置 0035: // v1 = 重み 0036: // v2 = 重みのインデックス 0037: // v3 = 法線 0038: // v4 = テクスチャー座標 0039: //------------------------------------------------------------------------------ 0040: // r0.w = Last blend weight 0041: // r1 = 重みのインデックス 0042: // r2 = 一時的な座標 0043: // r3 = 一時的な法線 0044: // r4 = カメラ空間での座標 0045: // r5 = カメラ空間での法線 0046: //------------------------------------------------------------------------------ 0047: // c9-c95 = 行列パレット 0048: // c8 = 平行光源 0049: // c7 = 環境光 0050: // c2-c5 = 射影行列 0051: // c1 = 光源方向 0052: // c0 = {1, ライトのべき乗, 0, 1020.01}; 0053: //------------------------------------------------------------------------------ 0054: // oPos = 位置 0055: // oD0 = 平行光 0056: // oD1 = すぺきゅらー 0057: // oT0 = テクスチャー座標 0058: //------------------------------------------------------------------------------ 0059: 0060: const char VertexShader0[] = { 0061: "vs.1.1 // シェーダ バージョン 1.1 \n"\ 0062: "mul r1,v2.zyxw,c0.wwww // Geforce3 で UBYTE4 がないのを補う \n"\ 0063: 0064: "mov a0.x,r1.x // 1 つめの行列を設定 \n"\ 0065: "m4x3 r4,v0,c[a0.x + 9] \n"\ 0066: "m3x3 r5,v3,c[a0.x + 9] \n"\ 0067: 0068: "mov r4.w,c0.x // 座標変換 \n"\ 0069: "m4x4 oPos,r4,c2 \n"\ 0070: 0071: "dp3 r5.w, r5, r5 // 法線の規格化 \n"\ 0072: "rsq r5.w, r5.w \n"\ 0073: "mul r5, r5, r5.w \n"\ 0074: 0075: "dp3 r1.x, r5, c1 // ライティング \n"\ 0076: "lit r1, r1 // \n"\ 0077: "mul r0, r1.y, c8 // 平行光源 \n"\ 0078: "add r0, r0, c7 // +環境光 \n"\ 0079: "min oD0, r0, c0.x // 1以下にクランプ \n"\ 0080: "mov oD1, c0.zzzz // すぺきゅらーの設定 \n"\ 0081: 0082: "mov oT0, v4 // テクスチャー座標のコピー " 0083: }; 0084: // ---------------------------------------------------------------------------- 0085: const char VertexShader1[] = { 0086: "vs.1.1 // シェーダ バージョン 1.1 \n"\ 0087: "mul r1,v2.zyxw,c0.wwww // Geforce3 で UBYTE4 がないのを補う \n"\ 0088: 0089: "dp3 r0.w,v1.xyz,c0.xzz // 最後の係数はウェイトの合計が1から算出 \n"\ 0090: "add r0.w,-r0.w,c0.x \n"\ 0091: 0092: "mov a0.x,r1.x // 1 つめの行列を設定 \n"\ 0093: "m4x3 r4,v0,c[a0.x + 9] \n"\ 0094: "m3x3 r5,v3,c[a0.x + 9] \n"\ 0095: "mul r4,r4,v1.xxxx // 係数をかけて合成する \n"\ 0096: "mul r5,r5,v1.xxxx \n"\ 0097: 0098: "mov a0.x,r1.y // 2 つめの行列を設定 \n"\ 0099: "m4x3 r2,v0,c[a0.x + 9] \n"\ 0100: "m3x3 r3,v3,c[a0.x + 9] \n"\ 0101: "mad r4,r2,r0.wwww,r4 // 係数をかけて合成する \n"\ 0102: "mad r5,r3,r0.wwww,r5 \n"\ 0103: 0104: "mov r4.w,c0.x // 座標変換 \n"\ 0105: "m4x4 oPos,r4,c2 \n"\ 0106: 0107: "dp3 r5.w, r5, r5 // 法線の規格化 \n"\ 0108: "rsq r5.w, r5.w \n"\ 0109: "mul r5, r5, r5.w \n"\ 0110: 0111: "dp3 r1.x, r5, c1 // ライティング \n"\ 0112: "lit r1, r1 // \n"\ 0113: "mul r0, r1.y, c8 // 平行光源 \n"\ 0114: "add r0, r0, c7 // +環境光 \n"\ 0115: "min oD0, r0, c0.x // 1以下にクランプ \n"\ 0116: "mov oD1, c0.zzzz // すぺきゅらーの設定 \n"\ 0117: 0118: "mov oT0, v4 // テクスチャー座標のコピー " 0119: }; 0120: // ---------------------------------------------------------------------------- 0121: const char VertexShader2[] = { 0122: "vs.1.1 // シェーダ バージョン 1.1 \n"\ 0123: "mul r1,v2.zyxw,c0.wwww // Geforce3 で UBYTE4 がないのを補う \n"\ 0124: 0125: "dp3 r0.w,v1.xyz,c0.xxz // 最後の係数はウェイトの合計が1から算出 \n"\ 0126: "add r0.w,-r0.w,c0.x \n"\ 0127: 0128: "mov a0.x,r1.x // 1 つめの行列を設定 \n"\ 0129: "m4x3 r4,v0,c[a0.x + 9] \n"\ 0130: "m3x3 r5,v3,c[a0.x + 9] \n"\ 0131: "mul r4,r4,v1.xxxx // 係数をかけて合成する \n"\ 0132: "mul r5,r5,v1.xxxx \n"\ 0133: 0134: "mov a0.x,r1.y // 2 つめの行列を設定 \n"\ 0135: "m4x3 r2,v0,c[a0.x + 9] \n"\ 0136: "m3x3 r3,v3,c[a0.x + 9] \n"\ 0137: "mad r4,r2,v1.yyyy,r4 // 係数をかけて合成する \n"\ 0138: "mad r5,r3,v1.yyyy,r5 \n"\ 0139: 0140: "mov a0.x,r1.z // 3 つめの行列を設定 \n"\ 0141: "m4x3 r2,v0,c[a0.x + 9] \n"\ 0142: "m3x3 r3,v3,c[a0.x + 9] \n"\ 0143: "mad r4,r2,r0.wwww,r4 // 係数をかけて合成する \n"\ 0144: "mad r5,r3,r0.wwww,r5 \n"\ 0145: 0146: "mov r4.w,c0.x // 座標変換 \n"\ 0147: "m4x4 oPos,r4,c2 \n"\ 0148: 0149: "dp3 r5.w, r5, r5 // 法線の規格化 \n"\ 0150: "rsq r5.w, r5.w \n"\ 0151: "mul r5, r5, r5.w \n"\ 0152: 0153: "dp3 r1.x, r5, c1 // ライティング \n"\ 0154: "lit r1, r1 // \n"\ 0155: "mul r0, r1.y, c8 // 平行光源 \n"\ 0156: "add r0, r0, c7 // +環境光 \n"\ 0157: "min oD0, r0, c0.x // 1以下にクランプ \n"\ 0158: "mov oD1, c0.zzzz // すぺきゅらーの設定 \n"\ 0159: 0160: "mov oT0, v4 // テクスチャー座標のコピー " 0161: }; 0162: // ---------------------------------------------------------------------------- 0163: const char VertexShader3[] = { 0164: "vs.1.1 // シェーダ バージョン 1.1 \n"\ 0165: "mul r1,v2.zyxw,c0.wwww // Geforce3 で UBYTE4 がないのを補う \n"\ 0166: 0167: "dp3 r0.w,v1.xyz,c0.xxx // 最後の係数はウェイトの合計が1から算出 \n"\ 0168: "add r0.w,-r0.w,c0.x \n"\ 0169: 0170: "mov a0.x,r1.x // 1 つめの行列を設定 \n"\ 0171: "m4x3 r4,v0,c[a0.x + 9] \n"\ 0172: "m3x3 r5,v3,c[a0.x + 9] \n"\ 0173: "mul r4,r4,v1.xxxx // 係数をかけて合成する \n"\ 0174: "mul r5,r5,v1.xxxx \n"\ 0175: 0176: "mov a0.x,r1.y // 2 つめの行列を設定 \n"\ 0177: "m4x3 r2,v0,c[a0.x + 9] \n"\ 0178: "m3x3 r3,v3,c[a0.x + 9] \n"\ 0179: "mad r4,r2,v1.yyyy,r4 // 係数をかけて合成する \n"\ 0180: "mad r5,r3,v1.yyyy,r5 \n"\ 0181: 0182: "mov a0.x,r1.z // 3 つめの行列を設定 \n"\ 0183: "m4x3 r2,v0,c[a0.x + 9] \n"\ 0184: "m3x3 r3,v3,c[a0.x + 9] \n"\ 0185: "mad r4,r2,v1.zzzz,r4 // 係数をかけて合成する \n"\ 0186: "mad r5,r3,v1.zzzz,r5 \n"\ 0187: 0188: "mov a0.x,r1.w // 4 つめの行列を設定 \n"\ 0189: "m4x3 r2,v0,c[a0.x + 9] \n"\ 0190: "m3x3 r3,v3,c[a0.x + 9] \n"\ 0191: "mad r4,r2,r0.wwww,r4 // 係数をかけて合成する \n"\ 0192: "mad r5,r3,r0.wwww,r5 \n"\ 0193: 0194: "mov r4.w,c0.x // 座標変換 \n"\ 0195: "m4x4 oPos,r4,c2 \n"\ 0196: 0197: "dp3 r5.w, r5, r5 // 法線の規格化 \n"\ 0198: "rsq r5.w, r5.w \n"\ 0199: "mul r5, r5, r5.w \n"\ 0200: 0201: "dp3 r1.x, r5, c1 // ライティング \n"\ 0202: "lit r1, r1 // \n"\ 0203: "mul r0, r1.y, c8 // 平行光源 \n"\ 0204: "add r0, r0, c7 // +環境光 \n"\ 0205: "min oD0, r0, c0.x // 1以下にクランプ \n"\ 0206: "mov oD1, c0.zzzz // すぺきゅらーの設定 \n"\ 0207: 0208: "mov oT0, v4 // テクスチャー座標のコピー " 0209: }; 0210: // ---------------------------------------------------------------------------- 0211: 0212: 0213: // ---------------------------------------------------------------------------- 0214: SMeshContainer::SMeshContainer(): 0215: pMesh(NULL), 0216: rgMaterials(NULL), 0217: pTextures(NULL), 0218: cpattr(0), 0219: iAttrSplit(0), 0220: cMaterials(0), 0221: pmcNext(NULL), 0222: szName(NULL), 0223: m_pSkinMesh(NULL), 0224: m_pAttrTable(NULL), 0225: m_pBoneMatrix(NULL), 0226: m_pBoneNamesBuf(NULL), 0227: m_pBoneOffsetBuf(NULL), 0228: m_pBoneOffsetMat(NULL), 0229: m_rgiAdjacency(NULL), 0230: m_numBoneComb(0), 0231: m_maxFaceInfl(0), 0232: m_pBoneCombinationBuf(NULL), 0233: m_Method(NONE), 0234: m_paletteSize(0), 0235: m_bUseSW(FALSE) 0236: { 0237: } 0238: // ---------------------------------------------------------------------------- 0239: SMeshContainer::~SMeshContainer() 0240: { 0241: DELETES(rgMaterials); 0242: 0243: if (pTextures) { 0244: for (DWORD i = 0; i < cMaterials; ++i) { 0245: RELEASE(pTextures[i]); 0246: } 0247: } 0248: DELETES(pTextures); 0249: 0250: RELEASE(pMesh); 0251: RELEASE(m_pSkinMesh); 0252: RELEASE(m_pBoneNamesBuf); 0253: RELEASE(m_pBoneOffsetBuf); 0254: RELEASE(m_pBoneCombinationBuf); 0255: 0256: DELETES(m_pBoneMatrix); 0257: DELETES(m_pAttrTable); 0258: DELETES(szName); 0259: DELETES(m_rgiAdjacency); 0260: delete pmcNext; 0261: } 0262: //----------------------------------------------------------------------------- 0263: //----------------------------------------------------------------------------- 0264: // メッシュのアニメーション管理 0265: //----------------------------------------------------------------------------- 0266: //----------------------------------------------------------------------------- 0267: 0268: //----------------------------------------------------------------------------- 0269: SFrame::SFrame(): 0270: pmcMesh(NULL), 0271: m_pPositionKeys(NULL), 0272: m_cPositionKeys(0), 0273: m_pScaleKeys(NULL), 0274: m_cScaleKeys(0), 0275: m_pRotateKeys(NULL), 0276: m_cRotateKeys(0), 0277: m_pMatrixKeys(NULL), 0278: m_cMatrixKeys(0), 0279: pframeAnimNext(NULL), 0280: pframeToAnimate(NULL), 0281: pframeSibling(NULL), 0282: pframeFirstChild(NULL), 0283: bAnimationFrame(false), 0284: szName(NULL) 0285: { 0286: D3DXMatrixIdentity(&matRot); 0287: D3DXMatrixIdentity(&matRotOrig); 0288: D3DXMatrixIdentity(&matTrans); 0289: } 0290: //----------------------------------------------------------------------------- 0291: SFrame::~SFrame() 0292: { 0293: DELETES(szName); 0294: delete pmcMesh; 0295: delete pframeFirstChild; 0296: delete pframeSibling; 0297: 0298: DELETES(m_pPositionKeys); 0299: DELETES(m_pRotateKeys); 0300: DELETES(m_pScaleKeys); 0301: DELETES(m_pMatrixKeys); 0302: } 0303: //----------------------------------------------------------------------------- 0304: // 時間の設定 0305: void SFrame::SetTime(float fGlobalTime) 0306: { 0307: UINT iKey; 0308: UINT dwp2; 0309: UINT dwp3; 0310: D3DXMATRIXA16 matResult; 0311: D3DXMATRIXA16 matTemp; 0312: float fTime1; 0313: float fTime2; 0314: float fLerpValue; 0315: D3DXVECTOR3 vScale; 0316: D3DXVECTOR3 vPos; 0317: D3DXQUATERNION quat; 0318: BOOL bAnimate = false; 0319: float fTime; 0320: 0321: if (m_pMatrixKeys ) { 0322: // 行列としてアニメが登録されていた場合 0323: 0324: // 時間にあったキーフレームを検索する 0325: fTime = (float)fmod(fGlobalTime, m_pMatrixKeys[m_cMatrixKeys-1].dwTime); 0326: for (iKey = 0 ;iKey < m_cMatrixKeys ; iKey++) { 0327: if ((float)m_pMatrixKeys[iKey].dwTime > fTime) { 0328: dwp3 = iKey; 0329: dwp2= (0<iKey)?(iKey - 1):iKey; 0330: break; 0331: } 0332: } 0333: fTime1 = (float)m_pMatrixKeys[dwp2].dwTime; 0334: fTime2 = (float)m_pMatrixKeys[dwp3].dwTime; 0335: // 時間の前後のキーフレームで近い方を選択する 0336: fLerpValue = ((fTime2 - fTime1) !=0)?( (fTime - fTime1) / (fTime2 - fTime1)):0; 0337: iKey = (0.5<fLerpValue)?dwp3:dwp2; 0338: pframeToAnimate->matRot = m_pMatrixKeys[iKey].mat; 0339: } else { 0340: D3DXMatrixIdentity(&matResult); 0341: // スケールのアニメが登録されていた場合 0342: if (m_pScaleKeys) { 0343: dwp2 = dwp3 = 0; 0344: 0345: // 時間にあったキーフレームを検索する 0346: fTime = (float)fmod(fGlobalTime, m_pScaleKeys[m_cScaleKeys-1].dwTime); 0347: for (iKey = 0 ;iKey < m_cScaleKeys ; iKey++) { 0348: if ((float)m_pScaleKeys[iKey].dwTime > fTime) { 0349: dwp3 = iKey; 0350: dwp2= (0<iKey)?(iKey - 1):iKey; 0351: break; 0352: } 0353: } 0354: fTime1 = (float)m_pScaleKeys[dwp2].dwTime; 0355: fTime2 = (float)m_pScaleKeys[dwp3].dwTime; 0356: 0357: // 線形補間して合成 0358: fLerpValue = ((fTime2 - fTime1) !=0)?( (fTime - fTime1) / (fTime2 - fTime1)):0; 0359: D3DXVec3Lerp(&vScale, 0360: &m_pScaleKeys[dwp2].vScale, 0361: &m_pScaleKeys[dwp3].vScale, 0362: fLerpValue); 0363: D3DXMatrixScaling(&matTemp, vScale.x, vScale.y, vScale.z); 0364: 0365: // 掛けた結果を保存する 0366: D3DXMatrixMultiply(&matResult, &matResult, &matTemp); 0367: 0368: bAnimate = true; 0369: } 0370: 0371: // 回転のアニメが登録されていた場合 0372: if (m_pRotateKeys ) { 0373: int i1 = 0; 0374: int i2 = 0; 0375: 0376: // 時間にあったキーフレームを検索する 0377: fTime = (float)fmod(fGlobalTime, m_pRotateKeys[m_cRotateKeys-1].dwTime); 0378: for (iKey = 0 ;iKey < m_cRotateKeys ; iKey++){ 0379: if (fTime < (float)m_pRotateKeys[iKey].dwTime){ 0380: i1 = (iKey > 0) ? iKey - 1 : 0; 0381: i2 = iKey; 0382: break; 0383: } 0384: } 0385: 0386: fTime1 = (float)m_pRotateKeys[i1].dwTime; 0387: fTime2 = (float)m_pRotateKeys[i2].dwTime; 0388: fLerpValue = ((fTime2 - fTime1) !=0)?( (fTime - fTime1) / (fTime2 - fTime1)):0; 0389: 0390: // 球状平方補間して合成 0391: int i0 = i1 - 1; 0392: int i3 = i2 + 1; 0393: 0394: if(i0 < 0) i0 += m_cRotateKeys; 0395: if(i3 >= (INT) m_cRotateKeys) i3 -= m_cRotateKeys; 0396: 0397: D3DXQUATERNION qA, qB, qC; 0398: D3DXQuaternionSquadSetup(&qA, &qB, &qC, 0399: &m_pRotateKeys[i0].quatRotate, &m_pRotateKeys[i1].quatRotate, 0400: &m_pRotateKeys[i2].quatRotate, &m_pRotateKeys[i3].quatRotate); 0401: 0402: D3DXQuaternionSquad(&quat, &m_pRotateKeys[i1].quatRotate, &qA, &qB, &qC, fLerpValue); 0403: 0404: quat.w = -quat.w; 0405: D3DXMatrixRotationQuaternion(&matTemp, &quat); 0406: // 掛けた結果を保存する 0407: D3DXMatrixMultiply(&matResult, &matResult, &matTemp); 0408: 0409: bAnimate = true; 0410: } 0411: 0412: // 平行移動のアニメが登録されていた場合 0413: if (m_pPositionKeys) { 0414: dwp2=dwp3=0; 0415: // 時間にあったキーフレームを検索する 0416: fTime = (float)fmod(fGlobalTime, m_pPositionKeys[m_cPositionKeys-1].dwTime); 0417: for (iKey = 0 ;iKey < m_cPositionKeys ; iKey++) { 0418: if ((float)m_pPositionKeys[iKey].dwTime > fTime) { 0419: dwp3 = iKey; 0420: dwp2= (0<iKey)?(iKey - 1):iKey; 0421: break; 0422: } 0423: } 0424: 0425: // 線形補間して合成 0426: fTime1 = (float)m_pPositionKeys[dwp2].dwTime; 0427: fTime2 = (float)m_pPositionKeys[dwp3].dwTime; 0428: fLerpValue = ((fTime2 - fTime1) !=0)?( (fTime - fTime1) / (fTime2 - fTime1)):0; 0429: D3DXVec3Lerp((D3DXVECTOR3*)&vPos, 0430: &m_pPositionKeys[dwp2].vPos, 0431: &m_pPositionKeys[dwp3].vPos, 0432: fLerpValue); 0433: D3DXMatrixTranslation(&matTemp, vPos.x, vPos.y, vPos.z); 0434: 0435: // 掛けた結果を保存する 0436: D3DXMatrixMultiply(&matResult, &matResult, &matTemp); 0437: bAnimate = true; 0438: } else { 0439: // 平行移動の場合はアニメが無ければディフォルトの位置を指定する 0440: D3DXMatrixTranslation(&matTemp 0441: , pframeToAnimate->matRotOrig._41 0442: , pframeToAnimate->matRotOrig._42 0443: , pframeToAnimate->matRotOrig._43); 0444: D3DXMatrixMultiply(&matResult, &matResult, &matTemp); 0445: } 0446: 0447: if (bAnimate) pframeToAnimate->matRot = matResult; 0448: } 0449: } 0450: //----------------------------------------------------------------------------- 0451: // 自分の子兄弟でszFrameの名前をもったやつがいるか調べる 0452: SFrame *SFrame::FindFrame(char *szFrame) 0453: { 0454: SFrame *pframe; 0455: 0456: // 名前が同じなら名乗り出る 0457: if ((szName != NULL) && (strcmp(szName, szFrame) == 0)) return this; 0458: 0459: // 後は、子供を伝った後、先頭の子供の兄弟から次々に検索する 0460: if (pframeFirstChild != NULL) { 0461: pframe = pframeFirstChild->FindFrame(szFrame); 0462: if (pframe != NULL) return pframe; 0463: } 0464: if (pframeSibling != NULL) { 0465: pframe = pframeSibling->FindFrame(szFrame); 0466: if (pframe != NULL) return pframe; 0467: } 0468: 0469: return NULL; 0470: } 0471: //----------------------------------------------------------------------------- 0472: // 行列を最初の(重心中心の)行列に初期化する 0473: void SFrame::ResetMatrix() 0474: { 0475: matRot = matRotOrig; 0476: D3DXMatrixIdentity(&matTrans); 0477: 0478: if (pframeFirstChild != NULL) pframeFirstChild->ResetMatrix(); 0479: if (pframeSibling != NULL) pframeSibling->ResetMatrix(); 0480: } 0481: //----------------------------------------------------------------------------- 0482: // フレームを追加する 0483: void SFrame::AddFrame(SFrame *pframe) 0484: { 0485: if (pframeFirstChild == NULL) { 0486: pframeFirstChild = pframe; 0487: } else { 0488: pframe->pframeSibling = pframeFirstChild->pframeSibling; 0489: pframeFirstChild->pframeSibling = pframe; 0490: } 0491: // root root root 0492: // | | | 0493: // child① - Sibling child① - Sibling② child① - Sibling③ - Sibling② 0494: // の順で詰まっていく 0495: } 0496: //----------------------------------------------------------------------------- 0497: // 先頭に新しいメッシュを追加する 0498: void SFrame::AddMesh(SMeshContainer *pmc) 0499: { 0500: pmc->pmcNext = pmcMesh; 0501: pmcMesh = pmc; 0502: } 0503: //----------------------------------------------------------------------------- 0504: // 重心を求める 0505: //----------------------------------------------------------------------------- 0506: HRESULT SFrame::CalculateSum( D3DXMATRIX *pmatCur, D3DXVECTOR3 *pvCenter, UINT *pcVertices) 0507: { 0508: HRESULT hr = S_OK; 0509: PBYTE pbPoints = NULL; 0510: UINT cVerticesLocal = 0; 0511: D3DXVECTOR3 vTransformedCur; 0512: UINT iPoint; 0513: SMeshContainer *pmcCur; 0514: SFrame *pCur; 0515: UINT cVertices; 0516: D3DXMATRIXA16 matLocal; 0517: 0518: D3DXMatrixMultiply(&matLocal, &this->matRot, pmatCur); 0519: 0520: for(pmcCur = this->pmcMesh ; pmcCur ; pmcCur = pmcCur->pmcNext ){ 0521: DWORD fvfsize = D3DXGetFVFVertexSize(pmcCur->pMesh->GetFVF()); 0522: 0523: cVertices = pmcCur->pMesh->GetNumVertices(); 0524: 0525: if (FAILED(hr = pmcCur->pMesh->LockVertexBuffer(0, &pbPoints))) goto e_Exit; 0526: 0527: PBYTE pbCur = pbPoints; 0528: for( iPoint=0 ; iPoint < cVertices; iPoint++, pbCur += fvfsize) { 0529: D3DXVECTOR3 *pvCur = (D3DXVECTOR3*)pbCur; 0530: 0531: if ((pvCur->x != 0.0) || (pvCur->y != 0.0) || (pvCur->z != 0.0)) { 0532: cVerticesLocal++; 0533: 0534: D3DXVec3TransformCoord(&vTransformedCur, pvCur, &matLocal); 0535: 0536: pvCenter->x += vTransformedCur.x; 0537: pvCenter->y += vTransformedCur.y; 0538: pvCenter->z += vTransformedCur.z; 0539: } 0540: } 0541: pmcCur->pMesh->UnlockVertexBuffer(); 0542: pbPoints = NULL; 0543: } 0544: 0545: *pcVertices += cVerticesLocal; 0546: 0547: for(pCur = this->pframeFirstChild ; pCur ; pCur = pCur->pframeSibling){ 0548: hr = pCur->CalculateSum( &matLocal, pvCenter, pcVertices); 0549: if (FAILED(hr)) goto e_Exit; 0550: } 0551: 0552: e_Exit: 0553: if (pbPoints != NULL) pmcCur->pMesh->UnlockVertexBuffer(); 0554: 0555: return hr; 0556: } 0557: //----------------------------------------------------------------------------- 0558: // 半径の計算 0559: //----------------------------------------------------------------------------- 0560: HRESULT SFrame::CalculateRadius(D3DXMATRIX *pmatCur, D3DXVECTOR3 *pvCenter, float *pfRadiusSq) 0561: { 0562: HRESULT hr = S_OK; 0563: PBYTE pbPoints = NULL; 0564: PBYTE pbCur; 0565: D3DXVECTOR3 *pvCur; 0566: D3DXVECTOR3 vDist;; 0567: UINT iPoint; 0568: UINT cVertices; 0569: SMeshContainer *pmcCur; 0570: SFrame *pCur; 0571: float fRadiusLocalSq; 0572: float fDistSq; 0573: D3DXMATRIXA16 matLocal; 0574: 0575: D3DXMatrixMultiply(&matLocal, &this->matRot, pmatCur); 0576: 0577: pmcCur = this->pmcMesh; 0578: fRadiusLocalSq = *pfRadiusSq; 0579: while (pmcCur != NULL) { 0580: DWORD fvfsize = D3DXGetFVFVertexSize(pmcCur->pMesh->GetFVF()); 0581: 0582: cVertices = pmcCur->pMesh->GetNumVertices(); 0583: 0584: hr = pmcCur->pMesh->LockVertexBuffer(0, &pbPoints); 0585: if (FAILED(hr)) goto e_Exit; 0586: 0587: for( iPoint=0, pbCur = pbPoints; iPoint < cVertices; iPoint++, pbCur += fvfsize ) { 0588: pvCur = (D3DXVECTOR3*)pbCur; 0589: 0590: if ((pvCur->x == 0.0) && (pvCur->y == 0.0) && (pvCur->z == 0.0)) continue; 0591: 0592: D3DXVec3TransformCoord(&vDist, pvCur, &matLocal); 0593: 0594: vDist -= *pvCenter; 0595: 0596: fDistSq = D3DXVec3LengthSq(&vDist); 0597: 0598: if( fDistSq > fRadiusLocalSq ) fRadiusLocalSq = fDistSq; 0599: } 0600: 0601: 0602: pmcCur->pMesh->UnlockVertexBuffer(); 0603: pbPoints = NULL; 0604: 0605: pmcCur = pmcCur->pmcNext; 0606: } 0607: 0608: *pfRadiusSq = fRadiusLocalSq; 0609: 0610: pCur = this->pframeFirstChild; 0611: while (pCur != NULL) { 0612: hr = pCur->CalculateRadius( &matLocal, pvCenter, pfRadiusSq); 0613: if (FAILED(hr)) goto e_Exit; 0614: 0615: pCur = pCur->pframeSibling; 0616: } 0617: 0618: e_Exit: 0619: if (pbPoints != NULL) pmcCur->pMesh->UnlockVertexBuffer(); 0620: 0621: return hr; 0622: } 0623: //----------------------------------------------------------------------------- 0624: // バウンディング球の計算 0625: //----------------------------------------------------------------------------- 0626: HRESULT SDrawElement::CalculateBoundingSphere() 0627: { 0628: HRESULT hr = S_OK; 0629: D3DXVECTOR3 vCenter(0,0,0); 0630: UINT cVertices = 0; 0631: float fRadiusSq = 0; 0632: D3DXMATRIXA16 matCur; 0633: 0634: D3DXMatrixIdentity(&matCur); 0635: hr = this->pframeRoot->CalculateSum(&matCur, &vCenter, &cVertices); 0636: if (FAILED(hr)) goto e_Exit; 0637: 0638: if (cVertices > 0) { 0639: vCenter /= (float)cVertices; 0640: 0641: D3DXMatrixIdentity(&matCur); 0642: hr = this->pframeRoot->CalculateRadius(&matCur, &vCenter, &fRadiusSq); 0643: if (FAILED(hr)) goto e_Exit; 0644: } 0645: 0646: this->fRadius = (float)sqrt((double)fRadiusSq);; 0647: this->vCenter = vCenter; 0648: e_Exit: 0649: return hr; 0650: } 0651: //----------------------------------------------------------------------------- 0652: SDrawElement::SDrawElement(): 0653: vCenter(0.0,0.0,0.0), 0654: fRadius(1.0), 0655: szName(NULL), 0656: pframeRoot(NULL), 0657: pframeAnimHead(NULL) 0658: { 0659: } 0660: //----------------------------------------------------------------------------- 0661: SDrawElement::~SDrawElement() 0662: { 0663: delete pframeRoot; 0664: delete [] szName; 0665: } 0666: //----------------------------------------------------------------------------- 0667: // 先頭にアニメーションフレームを追加する 0668: void SDrawElement::AddAnimationFrame(SFrame *pframeAnim) 0669: { 0670: pframeAnim->pframeAnimNext = pframeAnimHead; 0671: pframeAnimHead = pframeAnim; 0672: } 0673: //----------------------------------------------------------------------------- 0674: // 名前からフレームを検索する 0675: SFrame *SDrawElement::FindFrame(char *szName) 0676: { 0677: if (pframeRoot == NULL) return NULL; 0678: return pframeRoot->FindFrame(szName); 0679: } 0680: 0681: //----------------------------------------------------------------------------- 0682: // コンストラクタ 0683: //----------------------------------------------------------------------------- 0684: CSkinModel::CSkinModel() 0685: { 0686: m_szPath[0] = '\0'; 0687: m_pD3DDev = NULL; 0688: m_1st_time = 0; 0689: m_pdeMesh = NULL; 0690: 0691: m_dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL | D3DFVF_TEX1; 0692: 0693: m_method = D3DINDEXEDVS; 0694: 0695: m_pBoneMatrices = NULL; 0696: m_maxBones = 0; 0697: } 0698: //----------------------------------------------------------------------------- 0699: // 読み込んだファイルを解読する 0700: //----------------------------------------------------------------------------- 0701: HRESULT CSkinModel::_LoadMeshHierarchy(LPDIRECT3DDEVICE8 pD3DDev) 0702: { 0703: HRESULT hr = S_OK; 0704: const TCHAR* pszFile = m_szPath; 0705: SDrawElement *pdeMesh = NULL; 0706: LPDIRECTXFILE pxofapi = NULL; // DirectXFile オブジェクト 0707: LPDIRECTXFILEENUMOBJECT pxofenum = NULL; // DirectXFile 列挙オブジェクト 0708: LPDIRECTXFILEDATA pxofobjCur = NULL; // DirectXFile データ オブジェクト 0709: DWORD dwOptions = 0; 0710: int cchFileName; 0711: 0712: if (pszFile == NULL) return E_INVALIDARG;// ありえないけど、一応・・・ 0713: 0714: pdeMesh = new SDrawElement(); 0715: delete pdeMesh->pframeRoot; 0716: pdeMesh->pframeAnimHead = NULL; 0717: 0718: pdeMesh->pframeRoot = new SFrame(); 0719: if (pdeMesh->pframeRoot == NULL) {// メモリ不足 0720: hr = E_OUTOFMEMORY; 0721: goto e_Exit; 0722: } 0723: 0724: cchFileName = strlen(m_szPath); 0725: if (cchFileName < 2) {// 有効なファイル名でないなら失敗扱い 0726: hr = E_FAIL; 0727: goto e_Exit; 0728: } 0729: 0730: // ------------------------------------------------------------------------ 0731: // XFile の実際の読み込み 0732: if (FAILED(hr = DirectXFileCreate(&pxofapi))) goto e_Exit; 0733: 0734: // カスタム テンプレートを登録する 0735: hr = pxofapi->RegisterTemplates((LPVOID)D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES); 0736: if (FAILED(hr)) goto e_Exit; 0737: 0738: // 列挙オブジェクトを生成する 0739: // 列挙オブジェクトは、グローバル ユニーク識別子 (GUID) または名前でデータ オブジェクトを取得するのに使う 0740: if (FAILED(hr = pxofapi->CreateEnumObject( 0741: (LPVOID)m_szPath // DXFILELOAD_FROMFILE のときはファイル名 0742: , DXFILELOAD_FROMFILE // 「ファイル」からデータを読み取る 0743: , &pxofenum // 作成された列挙オブジェクト 0744: ))) goto e_Exit; 0745: 0746: 0747: // ------------------------------------------------------------------------ 0748: // データを読み込んで、フレームにがんがん登録していく 0749: while (SUCCEEDED(pxofenum->GetNextDataObject(&pxofobjCur))) { 0750: hr = pdeMesh->pframeRoot->LoadFrames(pxofobjCur, pdeMesh, dwOptions, *this); 0751: RELEASE(pxofobjCur); 0752: 0753: if (FAILED(hr)) goto e_Exit; 0754: } 0755: 0756: // ------------------------------------------------------------------------ 0757: // 骨構造の行列を構成する 0758: hr = pdeMesh->pframeRoot->FindBones(pdeMesh); 0759: if (FAILED(hr)) goto e_Exit; 0760: 0761: // ------------------------------------------------------------------------ 0762: // ファイル名を保存しておく 0763: delete []pdeMesh->szName; 0764: pdeMesh->szName = new char[cchFileName+1]; 0765: if (pdeMesh->szName == NULL) { 0766: hr = E_OUTOFMEMORY;// メモリ不足 0767: goto e_Exit; 0768: } 0769: memcpy(pdeMesh->szName, m_szPath, cchFileName+1); 0770: 0771: // ------------------------------------------------------------------------ 0772: // 現在登録されているモデルを削除し。読み込んだモデルを選択オブジェクトにする 0773: _DeleteSelectedMesh(); 0774: m_pdeMesh = pdeMesh; 0775: 0776: // ------------------------------------------------------------------------ 0777: // ときどき使うのでバウンディング球を作成しておく 0778: if (FAILED(hr = pdeMesh->CalculateBoundingSphere())) goto e_Exit; 0779: 0780: // 射影行列を設定しておく 0781: _SetProjectionMatrix(); 0782: 0783: // 現在の時間とループするフレーム数を設定する 0784: m_pdeMesh->fCurTime = 0.0f; 0785: 0786: // アニメをしないときの(全体移動の)行列を保存しておく 0787: D3DXMatrixTranslation(&m_pdeMesh->pframeRoot->matRot, 0788: -pdeMesh->vCenter.x, 0789: -pdeMesh->vCenter.y, 0790: -pdeMesh->vCenter.z); 0791: m_pdeMesh->pframeRoot->matRotOrig = m_pdeMesh->pframeRoot->matRot; 0792: 0793: e_Exit: 0794: // もう使わないものを開放 0795: RELEASE(pxofobjCur); 0796: RELEASE(pxofenum); 0797: RELEASE(pxofapi); 0798: if (FAILED(hr)) delete pdeMesh; 0799: 0800: return hr; 0801: } 0802: //----------------------------------------------------------------------------- 0803: // 骨の構造の解読 0804: //----------------------------------------------------------------------------- 0805: HRESULT SFrame::FindBones(SDrawElement *pde) 0806: { 0807: HRESULT hr = S_OK; 0808: 0809: for(SMeshContainer *pMc=this->pmcMesh ; pMc ; pMc=pMc->pmcNext ){ 0810: if (pMc->m_pSkinMesh) { 0811: char** pBoneName = static_cast<char**>(pMc->m_pBoneNamesBuf->GetBufferPointer()); 0812: for (DWORD i = 0; i < pMc->m_pSkinMesh->GetNumBones(); ++i) { 0813: // 骨のフレームの行列を骨の行列に設定する 0814: pMc->m_pBoneMatrix[i] = &(pde->FindFrame(pBoneName[i])->matCombined); 0815: } 0816: } 0817: } 0818: 0819: // 子供や子供兄弟も作成する 0820: for(SFrame *pChild=this->pframeFirstChild ; pChild ; pChild = pChild->pframeSibling ){ 0821: if (FAILED(hr = pChild->FindBones(pde))) return hr; 0822: } 0823: 0824: return S_OK; 0825: } 0826: //----------------------------------------------------------------------------- 0827: // フレームの読み込み 0828: //----------------------------------------------------------------------------- 0829: HRESULT SFrame::LoadFrames(LPDIRECTXFILEDATA pxofobjCur, SDrawElement *pde, 0830: DWORD options, CSkinModel &model) 0831: { 0832: HRESULT hr = S_OK; 0833: LPDIRECTXFILEDATA pxofobjChild = NULL; 0834: LPDIRECTXFILEOBJECT pxofChild = NULL; 0835: const GUID *type; 0836: DWORD cbSize; 0837: D3DXMATRIX *pmatNew; 0838: DWORD cchName; 0839: 0840: // タイプを調べて、種類に応じたロードを行う 0841: if (FAILED(hr = pxofobjCur->GetType(&type))) goto e_Exit; 0842: 0843: if(TID_D3DRMMesh==*type){ 0844: // ★D3D RM の頃からの伝統ある(?)メッシュファイル 0845: hr = this->_LoadMesh(pxofobjCur, options, model); 0846: if (FAILED(hr))goto e_Exit; 0847: }else 0848: if(TID_D3DRMFrameTransformMatrix==*type){ 0849: // ★姿勢行列 0850: hr = pxofobjCur->GetData(NULL, &cbSize, (PVOID*)&pmatNew); 0851: if (FAILED(hr)) goto e_Exit; 0852: // フレームを呼び出した(親の)フレームの行列を設定する 0853: this->matRot = *pmatNew; 0854: this->matRotOrig = *pmatNew; 0855: }else 0856: if(TID_D3DRMAnimationSet==*type){ 0857: // ★アニメーションの集合 0858: this->_LoadAnimationSet(pxofobjCur, pde, options, model); 0859: }else 0860: if(TID_D3DRMAnimation==*type){ 0861: // ★アニメーション 0862: this->_LoadAnimation(pxofobjCur, pde, options, model); 0863: }else 0864: if(TID_D3DRMFrame==*type){ 0865: // ★さらに新規フレーム 0866: // メモリ確保 0867: SFrame *pframeCur; 0868: if (NULL == (pframeCur = new SFrame())) { 0869: hr = E_OUTOFMEMORY; goto e_Exit; 0870: } 0871: // 名前があれば名前を読み込む 0872: if (FAILED(hr = pxofobjCur->GetName(NULL, &cchName))) goto e_Exit; 0873: if (cchName > 0) { 0874: if (NULL == (pframeCur->szName = new char[cchName])) { 0875: hr = E_OUTOFMEMORY; 0876: goto e_Exit; 0877: } 0878: if (FAILED(hr = pxofobjCur->GetName(pframeCur->szName, &cchName))) goto e_Exit; 0879: } 0880: // 新規フレームの追加 0881: this->AddFrame(pframeCur); 0882: 0883: // 子供のデータをがんがん読み込む 0884: while (SUCCEEDED(pxofobjCur->GetNextObject(&pxofChild))) { 0885: hr = pxofChild->QueryInterface(IID_IDirectXFileData,(LPVOID *)&pxofobjChild); 0886: if (SUCCEEDED(hr)) {// 子供に FileData を要求して、FileData があったら再起的に読み込む 0887: hr = pframeCur->LoadFrames(pxofobjChild, pde, options, model); 0888: if (FAILED(hr)) goto e_Exit; 0889: RELEASE(pxofobjChild); 0890: } 0891: RELEASE(pxofChild); 0892: } 0893: } 0894: 0895: e_Exit: 0896: RELEASE(pxofobjChild); 0897: RELEASE(pxofChild); 0898: return hr; 0899: } 0900: //----------------------------------------------------------------------------- 0901: // モデルの読み込み 0902: //----------------------------------------------------------------------------- 0903: HRESULT SFrame::_LoadMesh(LPDIRECTXFILEDATA pxofobjCur, DWORD options, CSkinModel &model) 0904: { 0905: HRESULT hr = S_OK; 0906: SMeshContainer *pmcMesh = NULL; 0907: LPD3DXBUFFER pbufMaterials = NULL; 0908: LPD3DXBUFFER pbufAdjacency = NULL; 0909: DWORD cchName; 0910: UINT cFaces; 0911: LPDWORD pAdjacencyIn; 0912: 0913: // メモリの確保 0914: if (NULL == (pmcMesh = new SMeshContainer())) { 0915: hr = E_OUTOFMEMORY; goto e_Exit; 0916: } 0917: 0918: // 名前を調べる 0919: if (FAILED(hr = pxofobjCur->GetName(NULL, &cchName))) goto e_Exit; 0920: if (cchName > 0) { 0921: if (NULL == (pmcMesh->szName=new char[cchName])) { 0922: hr = E_OUTOFMEMORY; goto e_Exit; 0923: } 0924: if (FAILED(hr=pxofobjCur->GetName(pmcMesh->szName, &cchName))) goto e_Exit; 0925: } 0926: // XFile を読み込む 0927: hr = D3DXLoadSkinMeshFromXof(pxofobjCur, options, model.GetDevice(), &pbufAdjacency, &pbufMaterials, &pmcMesh->cMaterials, 0928: &pmcMesh->m_pBoneNamesBuf, &pmcMesh->m_pBoneOffsetBuf, &pmcMesh->m_pSkinMesh); 0929: if (FAILED(hr)) { 0930: if (hr == D3DXERR_LOADEDMESHASNODATA) hr = S_OK; 0931: goto e_Exit; 0932: } 0933: 0934: // 各ポリゴンに関する隣接面の情報をコピーする 0935: cFaces = pmcMesh->m_pSkinMesh->GetNumFaces(); 0936: pAdjacencyIn = static_cast<LPDWORD>(pbufAdjacency->GetBufferPointer()); 0937: if (NULL == (pmcMesh->m_rgiAdjacency=new DWORD[cFaces * 3])) { 0938: hr = E_OUTOFMEMORY; goto e_Exit; 0939: } 0940: memcpy(pmcMesh->m_rgiAdjacency, pAdjacencyIn, cFaces * 3 * sizeof(DWORD)); 0941: 0942: // スキンのデータを処理する 0943: if (pmcMesh->m_pSkinMesh->GetNumBones()) { 0944: // 骨の数の計算 0945: model.SetMaxBorns(max(pmcMesh->m_pSkinMesh->GetNumBones(), model.GetMaxBorns())); 0946: // 骨で使う行列分のメモリの確保 0947: pmcMesh->m_pBoneMatrix = new D3DXMATRIX*[pmcMesh->m_pSkinMesh->GetNumBones()]; 0948: if (pmcMesh->m_pBoneMatrix == NULL) goto e_Exit; 0949: pmcMesh->m_pBoneOffsetMat = reinterpret_cast<D3DXMATRIX*>(pmcMesh->m_pBoneOffsetBuf->GetBufferPointer()); 0950: // 実際に表示で使うための(取り扱いやすい)メッシュを構成する 0951: if (FAILED(hr = model.GenerateMesh(pmcMesh))) goto e_Exit; 0952: } else { 0953: pmcMesh->m_pSkinMesh->GetOriginalMesh(&(pmcMesh->pMesh)); 0954: pmcMesh->m_pSkinMesh->Release(); // もう使わないので開放 0955: pmcMesh->m_pSkinMesh = NULL; // 骨がないのでスキンメッシュではない 0956: pmcMesh->cpattr = pmcMesh->cMaterials; // 質感を引っ張る 0957: } 0958: 0959: if ((pbufMaterials == NULL) || (pmcMesh->cMaterials == 0)) { 0960: // 質感情報なければ適当なものを作成 0961: pmcMesh->rgMaterials = new D3DMATERIAL8[1]; 0962: if (pmcMesh->rgMaterials == NULL) { 0963: hr = E_OUTOFMEMORY; goto e_Exit; 0964: } 0965: memset(pmcMesh->rgMaterials, 0, sizeof(D3DMATERIAL8)); 0966: pmcMesh->rgMaterials[0].Diffuse.r = 0.5f; 0967: pmcMesh->rgMaterials[0].Diffuse.g = 0.5f; 0968: pmcMesh->rgMaterials[0].Diffuse.b = 0.5f; 0969: pmcMesh->rgMaterials[0].Specular = pmcMesh->rgMaterials[0].Diffuse; 0970: // ダミーテクスチャー 0971: pmcMesh->pTextures = new LPDIRECT3DTEXTURE8[1]; 0972: if (pmcMesh->pTextures == NULL) { 0973: hr = E_OUTOFMEMORY; goto e_Exit; 0974: } 0975: pmcMesh->pTextures[0] = NULL; 0976: } else { 0977: // 質感情報あれば読み込む 0978: pmcMesh->rgMaterials = new D3DMATERIAL8[pmcMesh->cMaterials]; 0979: pmcMesh->pTextures = new LPDIRECT3DTEXTURE8[pmcMesh->cMaterials]; 0980: if (pmcMesh->rgMaterials == NULL || pmcMesh->pTextures == NULL) { 0981: hr = E_OUTOFMEMORY; 0982: goto e_Exit; 0983: } 0984: 0985: LPD3DXMATERIAL pMaterials = (LPD3DXMATERIAL)pbufMaterials->GetBufferPointer(); 0986: 0987: for (UINT i = 0; i < pmcMesh->cMaterials; i++) { 0988: pmcMesh->rgMaterials[i] = pMaterials[i].MatD3D; 0989: // テクスチャーがあればロード 0990: pmcMesh->pTextures[i] = NULL; 0991: if (pMaterials[i].pTextureFilename != NULL) { 0992: hr = D3DXCreateTextureFromFile(model.GetDevice(), pMaterials[i].pTextureFilename, &(pmcMesh->pTextures[i])); 0993: if (FAILED(hr)) pmcMesh->pTextures[i] = NULL; 0994: } 0995: } 0996: } 0997: 0998: // 親のフレームにメッシュを登録する 0999: this->AddMesh(pmcMesh); 1000: pmcMesh = NULL; 1001: 1002: e_Exit: 1003: delete pmcMesh; 1004: 1005: RELEASE(pbufAdjacency); 1006: RELEASE(pbufMaterials); 1007: 1008: return hr; 1009: } 1010: //----------------------------------------------------------------------------- 1011: // アニメーションの集合のロード 1012: //----------------------------------------------------------------------------- 1013: HRESULT SFrame::_LoadAnimationSet(LPDIRECTXFILEDATA pxofobjCur, SDrawElement *pde, 1014: DWORD options, CSkinModel &model) 1015: { 1016: SFrame *pframeCur; 1017: const GUID *type; 1018: HRESULT hr = S_OK; 1019: LPDIRECTXFILEDATA pxofobjChild = NULL; 1020: LPDIRECTXFILEOBJECT pxofChild = NULL; 1021: DWORD cchName; 1022: 1023: // 新規にフレームを追加 1024: if (NULL == (pframeCur=new SFrame())) { 1025: hr = E_OUTOFMEMORY; goto e_Exit; 1026: } 1027: this->AddFrame(pframeCur); 1028: 1029: pframeCur->bAnimationFrame = true; // アニメーションのフレームであることを宣言 1030: 1031: // 名前を読み込む 1032: if (FAILED(hr = pxofobjCur->GetName(NULL, &cchName))) goto e_Exit; 1033: if (cchName > 0) { 1034: if (NULL == (pframeCur->szName = new char[cchName])) { 1035: hr = E_OUTOFMEMORY; goto e_Exit; 1036: } 1037: if (FAILED(hr = pxofobjCur->GetName(pframeCur->szName, &cchName))) goto e_Exit; 1038: } 1039: 1040: // 読める限りのデータを読んで、アニメーションのデータをロードする 1041: while (SUCCEEDED(pxofobjCur->GetNextObject(&pxofChild))) { 1042: hr = pxofChild->QueryInterface(IID_IDirectXFileData,(LPVOID *)&pxofobjChild); 1043: if (SUCCEEDED(hr)) { 1044: if (FAILED(hr = pxofobjChild->GetType(&type))) goto e_Exit; 1045: 1046: if( TID_D3DRMAnimation == *type ) {// アニメのデータだけ 1047: hr = pframeCur->_LoadAnimation(pxofobjChild, pde, options, model); 1048: if (FAILED(hr)) goto e_Exit; 1049: } 1050: RELEASE(pxofobjChild); 1051: } 1052: RELEASE(pxofChild); 1053: } 1054: 1055: e_Exit: 1056: RELEASE(pxofobjChild); 1057: RELEASE(pxofChild); 1058: return hr; 1059: } 1060: //----------------------------------------------------------------------------- 1061: // アニメのロード 1062: //----------------------------------------------------------------------------- 1063: HRESULT SFrame::_LoadAnimation(LPDIRECTXFILEDATA pxofobjCur, SDrawElement *pde, 1064: DWORD options, CSkinModel &model) 1065: { 1066: HRESULT hr = S_OK; 1067: SRotateKeyXFile *pFileRotateKey; 1068: SScaleKeyXFile *pFileScaleKey; 1069: SPositionKeyXFile *pFilePosKey; 1070: SMatrixKeyXFile *pFileMatrixKey; 1071: SFrame *pframeCur; 1072: LPDIRECTXFILEDATA pxofobjChild = NULL; 1073: LPDIRECTXFILEOBJECT pxofChild = NULL; 1074: LPDIRECTXFILEDATAREFERENCE pxofobjChildRef = NULL; 1075: const GUID *type; 1076: DWORD dwSize; 1077: PBYTE pData; 1078: DWORD dwKeyType; 1079: DWORD cKeys; 1080: DWORD iKey; 1081: DWORD cchName; 1082: char *szFrameName; 1083: 1084: // 新規にフレームを追加 1085: if (NULL == (pframeCur = new SFrame())) { 1086: hr = E_OUTOFMEMORY; goto e_Exit; 1087: } 1088: this->AddFrame(pframeCur); 1089: pde->AddAnimationFrame(pframeCur); // SDrawElement にアニメを追加 1090: 1091: pframeCur->bAnimationFrame = true; // アニメーションのフレームであることを宣言 1092: 1093: // 読める限りのデータを読んで、アニメーションのデータをロードする 1094: while (SUCCEEDED(pxofobjCur->GetNextObject(&pxofChild))) { 1095: // 参照をしらべる 1096: hr = pxofChild->QueryInterface(IID_IDirectXFileDataReference,(LPVOID *)&pxofobjChildRef); 1097: if (SUCCEEDED(hr)) { 1098: hr = pxofobjChildRef->Resolve(&pxofobjChild); 1099: if (SUCCEEDED(hr)) { 1100: // タイプを調べて、フレームの情報だけを抜き出す 1101: if (FAILED(hr = pxofobjChild->GetType(&type))) goto e_Exit; 1102: 1103: if( TID_D3DRMFrame == *type ) { 1104: if (pframeCur->pframeToAnimate != NULL) {// あるのか? 1105: hr = E_INVALIDARG; goto e_Exit; 1106: } 1107: 1108: // 名前を読み込む 1109: if (FAILED(hr = pxofobjChild->GetName(NULL, &cchName))) goto e_Exit; 1110: if (cchName == 0) { 1111: hr = E_INVALIDARG; goto e_Exit; 1112: } 1113: szFrameName = (char*)_alloca(cchName); 1114: if (szFrameName == NULL) { 1115: hr = E_OUTOFMEMORY; goto e_Exit; 1116: } 1117: if (FAILED(hr = pxofobjChild->GetName(szFrameName, &cchName))) goto e_Exit; 1118: 1119: // 名前からフレームを検索する 1120: pframeCur->pframeToAnimate = pde->FindFrame(szFrameName); 1121: if (pframeCur->pframeToAnimate == NULL) { 1122: hr = E_INVALIDARG; goto e_Exit; 1123: } 1124: } 1125: RELEASE(pxofobjChild); 1126: } 1127: RELEASE(pxofobjChildRef); 1128: } else { 1129: // 参照がなければデータを調べる 1130: hr = pxofChild->QueryInterface(IID_IDirectXFileData,(LPVOID *)&pxofobjChild); 1131: if (SUCCEEDED(hr)) 1132: { 1133: // タイプを調べて、種類に応じた処理を行う 1134: if (FAILED(hr = pxofobjChild->GetType(&type))) goto e_Exit; 1135: 1136: if ( TID_D3DRMFrame == *type ) {// フレーム 1137: hr = pframeCur->LoadFrames(pxofobjChild, pde, options, model); 1138: if (FAILED(hr)) goto e_Exit; 1139: } else if ( TID_D3DRMAnimationOptions == *type ) { 1140: // オプション(処理なし) 1141: } else if ( TID_D3DRMAnimationKey == *type ) { 1142: // アニメーションのキーフレームデータ 1143: if (FAILED(hr = pxofobjChild->GetData( NULL, &dwSize, (PVOID*)&pData ))) goto e_Exit; 1144: 1145: dwKeyType = ((DWORD*)pData)[0]; 1146: cKeys = ((DWORD*)pData)[1]; 1147: 1148: switch(dwKeyType){ 1149: case 0:// 回転 1150: if (pframeCur->m_pRotateKeys != NULL) { 1151: hr = E_INVALIDARG; goto e_Exit; 1152: } 1153: if (NULL==(pframeCur->m_pRotateKeys = new SRotateKey[cKeys])) { 1154: hr = E_OUTOFMEMORY; goto e_Exit; 1155: } 1156: pframeCur->m_cRotateKeys = cKeys; 1157: pFileRotateKey = (SRotateKeyXFile*)(pData + (sizeof(DWORD) * 2)); 1158: for (iKey = 0;iKey < cKeys; iKey++) { 1159: pframeCur->m_pRotateKeys[iKey].dwTime = pFileRotateKey->dwTime; 1160: pframeCur->m_pRotateKeys[iKey].quatRotate.x = pFileRotateKey->x; 1161: pframeCur->m_pRotateKeys[iKey].quatRotate.y = pFileRotateKey->y; 1162: pframeCur->m_pRotateKeys[iKey].quatRotate.z = pFileRotateKey->z; 1163: pframeCur->m_pRotateKeys[iKey].quatRotate.w = pFileRotateKey->w; 1164: pFileRotateKey++; 1165: } 1166: break; 1167: case 1:// 拡大縮小 1168: if (pframeCur->m_pScaleKeys != NULL) { 1169: hr = E_INVALIDARG; goto e_Exit; 1170: } 1171: if (NULL==(pframeCur->m_pScaleKeys = new SScaleKey[cKeys])) { 1172: hr = E_OUTOFMEMORY; goto e_Exit; 1173: } 1174: pframeCur->m_cScaleKeys = cKeys; 1175: pFileScaleKey = (SScaleKeyXFile*)(pData + (sizeof(DWORD) * 2)); 1176: for (iKey = 0;iKey < cKeys; iKey++) { 1177: pframeCur->m_pScaleKeys[iKey].dwTime = pFileScaleKey->dwTime; 1178: pframeCur->m_pScaleKeys[iKey].vScale = pFileScaleKey->vScale; 1179: pFileScaleKey++; 1180: } 1181: break; 1182: case 2:// 平行移動 1183: if (pframeCur->m_pPositionKeys != NULL) { 1184: hr = E_INVALIDARG; goto e_Exit; 1185: } 1186: if (NULL==(pframeCur->m_pPositionKeys = new SPositionKey[cKeys])) { 1187: hr = E_OUTOFMEMORY; goto e_Exit; 1188: } 1189: pframeCur->m_cPositionKeys = cKeys; 1190: pFilePosKey = (SPositionKeyXFile*)(pData + (sizeof(DWORD) * 2)); 1191: for (iKey = 0;iKey < cKeys; iKey++) { 1192: pframeCur->m_pPositionKeys[iKey].dwTime = pFilePosKey->dwTime; 1193: pframeCur->m_pPositionKeys[iKey].vPos = pFilePosKey->vPos; 1194: pFilePosKey++; 1195: } 1196: break; 1197: case 4:// 行列そのもの 1198: if (pframeCur->m_pMatrixKeys != NULL) { 1199: hr = E_INVALIDARG; goto e_Exit; 1200: } 1201: if (NULL==(pframeCur->m_pMatrixKeys = new SMatrixKey[cKeys])) { 1202: hr = E_OUTOFMEMORY; goto e_Exit; 1203: } 1204: pframeCur->m_cMatrixKeys = cKeys; 1205: pFileMatrixKey = (SMatrixKeyXFile*)(pData + (sizeof(DWORD) * 2)); 1206: for (iKey = 0;iKey < cKeys; iKey++) { 1207: pframeCur->m_pMatrixKeys[iKey].dwTime = pFileMatrixKey->dwTime; 1208: pframeCur->m_pMatrixKeys[iKey].mat = pFileMatrixKey->mat; 1209: pFileMatrixKey++; 1210: } 1211: break; 1212: default: 1213: hr = E_INVALIDARG; goto e_Exit; 1214: break; 1215: } 1216: } 1217: RELEASE(pxofobjChild); 1218: } 1219: } 1220: RELEASE(pxofChild); 1221: } 1222: 1223: e_Exit: 1224: RELEASE(pxofobjChild); 1225: RELEASE(pxofChild); 1226: RELEASE(pxofobjChildRef); 1227: return hr; 1228: } 1229: //----------------------------------------------------------------------------- 1230: // メッシュの生成(D3DNONINDEXED) 1231: //----------------------------------------------------------------------------- 1232: HRESULT CSkinModel::_GenerateMeshNonIndexed(SMeshContainer *pmcMesh) 1233: { 1234: LPD3DXBONECOMBINATION rgBoneCombinations; 1235: 1236: HRESULT hr = S_OK; 1237: hr = pmcMesh->m_pSkinMesh->ConvertToBlendedMesh 1238: ( 1239: D3DXMESH_MANAGED|D3DXMESHOPT_VERTEXCACHE, 1240: pmcMesh->m_rgiAdjacency, 1241: NULL, 1242: &pmcMesh->cpattr, 1243: &pmcMesh->m_pBoneCombinationBuf, 1244: NULL, 1245: NULL, 1246: &pmcMesh->pMesh 1247: ); 1248: if (FAILED(hr)) return hr; 1249: 1250: // calculate the max face influence count 1251: 1252: if ((pmcMesh->pMesh->GetFVF() & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) { 1253: pmcMesh->m_maxFaceInfl = 1 + ((pmcMesh->pMesh->GetFVF() & D3DFVF_POSITION_MASK) - D3DFVF_XYZRHW) / 2; 1254: } else { 1255: pmcMesh->m_maxFaceInfl = 1; 1256: } 1257: 1258: /* If the device can only do 2 matrix blends, ConvertToBlendedMesh cannot approximate all meshes to it 1259: Thus we split the mesh in two parts: The part that uses at most 2 matrices and the rest. The first is 1260: drawn using the device's HW vertex processing and the rest is drawn using SW vertex processing. */ 1261: if (this->GetCaps()->MaxVertexBlendMatrices <= 2) { 1262: // calculate the index of the attribute table to split on 1263: rgBoneCombinations = reinterpret_cast<LPD3DXBONECOMBINATION>(pmcMesh->m_pBoneCombinationBuf->GetBufferPointer()); 1264: 1265: for (pmcMesh->iAttrSplit = 0; pmcMesh->iAttrSplit < pmcMesh->cpattr; pmcMesh->iAttrSplit++) { 1266: DWORD cInfl = 0; 1267: for (DWORD iInfl = 0; iInfl < pmcMesh->m_maxFaceInfl; iInfl++) { 1268: if (rgBoneCombinations[pmcMesh->iAttrSplit].BoneId[iInfl] != UINT_MAX) { 1269: ++cInfl; 1270: } 1271: } 1272: if (this->GetCaps()->MaxVertexBlendMatrices < cInfl) break; 1273: } 1274: 1275: // if there is both HW and SW, add the Software Processing flag 1276: if (pmcMesh->iAttrSplit < pmcMesh->cpattr) { 1277: LPD3DXMESH pMeshTmp; 1278: 1279: hr = pmcMesh->pMesh->CloneMeshFVF(D3DXMESH_SOFTWAREPROCESSING|pmcMesh->pMesh->GetOptions(), 1280: pmcMesh->pMesh->GetFVF(), 1281: this->GetDevice(), &pMeshTmp); 1282: if (FAILED(hr)) return hr; 1283: 1284: pmcMesh->pMesh->Release(); 1285: pmcMesh->pMesh = pMeshTmp; 1286: pMeshTmp = NULL; 1287: } 1288: }else{ 1289: pmcMesh->iAttrSplit = pmcMesh->cpattr; 1290: } 1291: return hr; 1292: } 1293: //----------------------------------------------------------------------------- 1294: // メッシュの生成(D3DINDEXEDVS) 1295: //----------------------------------------------------------------------------- 1296: HRESULT CSkinModel::_GenerateMeshIndexedVs(SMeshContainer *pmcMesh) 1297: { 1298: HRESULT hr = S_OK; 1299: // 行列パレットの数を設定する(最大28) 1300: pmcMesh->m_paletteSize = min(28, pmcMesh->m_pSkinMesh->GetNumBones()); 1301: 1302: // アドレス レジスタが使えないならソフトウェアT&L 1303: DWORD flags = D3DXMESHOPT_VERTEXCACHE; 1304: if (D3DVS_VERSION(1, 1) <= this->GetCaps()->VertexShaderVersion ) { 1305: pmcMesh->m_bUseSW = false; 1306: flags |= D3DXMESH_MANAGED; 1307: } else { 1308: pmcMesh->m_bUseSW = true; 1309: flags |= D3DXMESH_SYSTEMMEM; 1310: } 1311: 1312: // インデックス付きのブレンドされたメッシュへ変換する 1313: hr = pmcMesh->m_pSkinMesh->ConvertToIndexedBlendedMesh(flags, pmcMesh->m_rgiAdjacency, pmcMesh->m_paletteSize, NULL, 1314: &pmcMesh->cpattr, &pmcMesh->m_pBoneCombinationBuf, NULL, NULL, &pmcMesh->pMesh); 1315: if (FAILED(hr)) return hr; 1316: 1317: // 最大の混合する数を調べる 1318: if ((pmcMesh->pMesh->GetFVF() & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) { 1319: pmcMesh->m_maxFaceInfl = ((pmcMesh->pMesh->GetFVF() & D3DFVF_POSITION_MASK) - D3DFVF_XYZRHW) / 2; 1320: } else { 1321: pmcMesh->m_maxFaceInfl = 1; 1322: } 1323: 1324: // FVF を変更して、それにあったメッシュを作成する 1325: DWORD newFVF = (pmcMesh->pMesh->GetFVF() & D3DFVF_POSITION_MASK) | D3DFVF_NORMAL | D3DFVF_TEX1 | D3DFVF_LASTBETA_UBYTE4; 1326: if (newFVF != pmcMesh->pMesh->GetFVF()) { 1327: LPD3DXMESH pMesh; 1328: hr = pmcMesh->pMesh->CloneMeshFVF(pmcMesh->pMesh->GetOptions(), newFVF, this->GetDevice(), &pMesh); 1329: if (!FAILED(hr)) { 1330: pmcMesh->pMesh->Release(); 1331: pmcMesh->pMesh = pMesh; 1332: pMesh = NULL; 1333: } 1334: } 1335: return hr; 1336: } 1337: //----------------------------------------------------------------------------- 1338: // メッシュの生成(D3DINDEXED) 1339: //----------------------------------------------------------------------------- 1340: HRESULT CSkinModel::_GenerateMeshIndexed(SMeshContainer *pmcMesh) 1341: { 1342: HRESULT hr = S_OK; 1343: DWORD maxFaceInfl; 1344: DWORD flags = D3DXMESHOPT_VERTEXCACHE; 1345: 1346: hr = pmcMesh->m_pSkinMesh->GetMaxFaceInfluences(&maxFaceInfl); 1347: if (FAILED(hr)) return hr; 1348: 1349: // 12 entry palette guarantees that any triangle (4 independent influences per vertex of a tri) 1350: // can be handled 1351: maxFaceInfl = min(maxFaceInfl, 12); 1352: 1353: if (this->GetCaps()->MaxVertexBlendMatrixIndex + 1 < maxFaceInfl) { 1354: // HW does not support indexed vertex blending. Use SW instead 1355: pmcMesh->m_paletteSize = min(256, pmcMesh->m_pSkinMesh->GetNumBones()); 1356: pmcMesh->m_bUseSW = true; 1357: flags |= D3DXMESH_SYSTEMMEM; 1358: } else { 1359: pmcMesh->m_paletteSize = min(this->GetCaps()->MaxVertexBlendMatrixIndex + 1, pmcMesh->m_pSkinMesh->GetNumBones()); 1360: pmcMesh->m_bUseSW = false; 1361: flags |= D3DXMESH_MANAGED; 1362: } 1363: 1364: hr = pmcMesh->m_pSkinMesh->ConvertToIndexedBlendedMesh(flags, pmcMesh->m_rgiAdjacency, pmcMesh->m_paletteSize, NULL, 1365: &pmcMesh->cpattr, &pmcMesh->m_pBoneCombinationBuf, NULL, NULL, &pmcMesh->pMesh); 1366: if (FAILED(hr)) return hr; 1367: 1368: // Here we are talking of max vertex influence which we determine from 1369: // the FVF of the returned mesh 1370: if ((pmcMesh->pMesh->GetFVF() & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) { 1371: pmcMesh->m_maxFaceInfl = ((pmcMesh->pMesh->GetFVF() & D3DFVF_POSITION_MASK) - D3DFVF_XYZRHW) / 2; 1372: } else { 1373: pmcMesh->m_maxFaceInfl = 1; 1374: } 1375: 1376: return hr; 1377: } 1378: //----------------------------------------------------------------------------- 1379: // メッシュの生成(SOFTWARE) 1380: //----------------------------------------------------------------------------- 1381: HRESULT CSkinModel::_GenerateMeshSoftware(SMeshContainer *pmcMesh) 1382: { 1383: HRESULT hr = S_OK; 1384: hr = pmcMesh->m_pSkinMesh->GenerateSkinnedMesh ( 1385: D3DXMESH_WRITEONLY, // メッシュの作成オプション 1386: 0.0f, // 最小ウェイト固定値 1387: pmcMesh->m_rgiAdjacency, // ソース メッシュに含まれる各面の 3 つの隣接面の配列へのポインタ 1388: NULL, // 最適化されたメッシュの面隣接性配列に使用する転送先バッファへのポインタ 1389: NULL, // face remap array 1390: NULL, // vertex remap buffer 1391: &pmcMesh->pMesh // 生成されたメッシュ 1392: ); 1393: if (FAILED(hr)) return hr; 1394: 1395: // アトリビュートを読み込む 1396: hr = pmcMesh->pMesh->GetAttributeTable(NULL, &pmcMesh->cpattr); 1397: if (FAILED(hr)) return hr; 1398: 1399: delete[] pmcMesh->m_pAttrTable; 1400: pmcMesh->m_pAttrTable = new D3DXATTRIBUTERANGE[pmcMesh->cpattr]; 1401: if (pmcMesh->m_pAttrTable == NULL) {// 格納するメモリが足りない 1402: hr = E_OUTOFMEMORY; 1403: return hr; 1404: } 1405: hr = pmcMesh->pMesh->GetAttributeTable(pmcMesh->m_pAttrTable, NULL); 1406: if (FAILED(hr)) return hr; 1407: 1408: // スキン メッシュの任意の 1 面に影響を与える、影響の数の最大値を読み込む 1409: hr = pmcMesh->m_pSkinMesh->GetMaxFaceInfluences(&pmcMesh->m_maxFaceInfl); 1410: if (FAILED(hr)) return hr; 1411: 1412: // 行列用の配列を用意する 1413: this->m_pBoneMatrices = new D3DXMATRIXA16[this->GetMaxBorns()]; 1414: if (this->m_pBoneMatrices == NULL) { 1415: hr = E_OUTOFMEMORY; 1416: return hr; 1417: } 1418: return hr; 1419: } 1420: //----------------------------------------------------------------------------- 1421: // メッシュの生成 1422: //----------------------------------------------------------------------------- 1423: HRESULT CSkinModel::GenerateMesh(SMeshContainer *pmcMesh) 1424: { 1425: HRESULT hr = S_OK; 1426: LPDIRECT3DDEVICE8 pD3DDev = NULL; 1427: DWORD cFaces = pmcMesh->m_pSkinMesh->GetNumFaces(); 1428: 1429: if (FAILED(hr=pmcMesh->m_pSkinMesh->GetDevice(&pD3DDev))) goto e_Exit; 1430: 1431: RELEASE(pmcMesh->pMesh); 1432: delete [] this->m_pBoneMatrices; 1433: 1434: pmcMesh->pMesh = NULL; 1435: this->m_pBoneMatrices = NULL; 1436: 1437: // 方法によって生成するものを変える 1438: switch(this->GetMethod()){ 1439: case D3DNONINDEXED: 1440: hr = _GenerateMeshNonIndexed(pmcMesh); 1441: break; 1442: case D3DINDEXEDVS: 1443: hr = _GenerateMeshIndexedVs(pmcMesh); 1444: break; 1445: case D3DINDEXED: 1446: hr = _GenerateMeshIndexed(pmcMesh); 1447: break; 1448: case SOFTWARE: 1449: hr = _GenerateMeshSoftware(pmcMesh); 1450: break; 1451: } 1452: if(SUCCEEDED(hr)) pmcMesh->m_Method = this->GetMethod(); 1453: 1454: e_Exit: 1455: 1456: RELEASE(pD3DDev); 1457: return hr; 1458: } 1459: //----------------------------------------------------------------------------- 1460: // 初期化 1461: //----------------------------------------------------------------------------- 1462: HRESULT CSkinModel::Init(DWORD time, LPDIRECT3DDEVICE8 pD3DDev, D3DCAPS8 &caps) 1463: { 1464: this->Set1stTime(time); 1465: this->_SetDevice(pD3DDev); 1466: 1467: if(pD3DDev){ 1468: // アスペクト比を求めるための D3DSURFACE_DESC の所得 1469: LPDIRECT3DSURFACE8 pBackBuffer; 1470: pD3DDev->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer ); 1471: pBackBuffer->GetDesc( &m_d3dsdBackBuffer ); 1472: pBackBuffer->Release(); 1473: 1474: m_d3dCaps = caps; 1475: } 1476: 1477: _CreateVertexShader(); 1478: 1479: return S_OK; 1480: } 1481: //----------------------------------------------------------------------------- 1482: // 頂点シェーダーの生成 1483: //----------------------------------------------------------------------------- 1484: HRESULT CSkinModel::_CreateVertexShader() 1485: { 1486: LPD3DXBUFFER pCode; 1487: HRESULT hr; 1488: 1489: // インデックススキニングのための頂点シェーダーの生成 1490: DWORD dwIndexedVertexDecl1[] = { 1491: D3DVSD_STREAM( 0 ), 1492: D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // Position of first mesh 1493: D3DVSD_REG( 2, D3DVSDT_D3DCOLOR ), // 合成する行列の指定 1494: D3DVSD_REG( 3, D3DVSDT_FLOAT3 ), // 法線 1495: D3DVSD_REG( 4, D3DVSDT_FLOAT2 ), // テクスチャー座標 1496: D3DVSD_END() 1497: }; 1498: 1499: DWORD dwIndexedVertexDecl2[] = { 1500: D3DVSD_STREAM( 0 ), 1501: D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // Position of first mesh 1502: D3DVSD_REG( 1, D3DVSDT_FLOAT1 ), // 合成の重み 1503: D3DVSD_REG( 2, D3DVSDT_D3DCOLOR ), // 合成する行列の指定 1504: D3DVSD_REG( 3, D3DVSDT_FLOAT3 ), // 法線 1505: D3DVSD_REG( 4, D3DVSDT_FLOAT2 ), // テクスチャー座標 1506: D3DVSD_END() 1507: }; 1508: 1509: DWORD dwIndexedVertexDecl3[] = { 1510: D3DVSD_STREAM( 0 ), 1511: D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // Position of first mesh 1512: D3DVSD_REG( 1, D3DVSDT_FLOAT2 ), // 合成の重み 1513: D3DVSD_REG( 2, D3DVSDT_D3DCOLOR ), // 合成する行列の指定 1514: D3DVSD_REG( 3, D3DVSDT_FLOAT3 ), // 法線 1515: D3DVSD_REG( 4, D3DVSDT_FLOAT2 ), // テクスチャー座標 1516: D3DVSD_END() 1517: }; 1518: 1519: DWORD dwIndexedVertexDecl4[] = { 1520: D3DVSD_STREAM( 0 ), 1521: D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // Position of first mesh 1522: D3DVSD_REG( 1, D3DVSDT_FLOAT3 ), // 合成の重み 1523: D3DVSD_REG( 2, D3DVSDT_D3DCOLOR ), // 合成する行列の指定 1524: D3DVSD_REG( 3, D3DVSDT_FLOAT3 ), // 法線 1525: D3DVSD_REG( 4, D3DVSDT_FLOAT2 ), // テクスチャー座標 1526: D3DVSD_END() 1527: }; 1528: 1529: DWORD* dwIndexedVertexDecl[] = { 1530: dwIndexedVertexDecl1, 1531: dwIndexedVertexDecl2, 1532: dwIndexedVertexDecl3, 1533: dwIndexedVertexDecl4, 1534: }; 1535: 1536: char *filename[] = { 1537: "skinmesh1.vsh", 1538: "skinmesh2.vsh", 1539: "skinmesh3.vsh", 1540: "skinmesh4.vsh", 1541: }; 1542: 1543: const char *shader_program[] = { 1544: VertexShader0, 1545: VertexShader1, 1546: VertexShader2, 1547: VertexShader3, 1548: }; 1549: const int size[] = { 1550: sizeof(VertexShader0)-1, 1551: sizeof(VertexShader1)-1, 1552: sizeof(VertexShader2)-1, 1553: sizeof(VertexShader3)-1, 1554: }; 1555: 1556: // アドレス レジスタが使えないならソフトウェアT&L 1557: DWORD bUseSW = (m_d3dCaps.VertexShaderVersion < D3DVS_VERSION(1, 1)); 1558: 1559: for (DWORD i = 0; i < 4; ++i) { 1560: // シェーダープログラムの読み込み 1561: if ( FAILED(hr = D3DXAssembleShader( shader_program[i] , size[i], 0 , NULL , &pCode , NULL)) ) return hr; 1562: 1563: // 頂点シェーダーの生成 1564: if( FAILED( hr = m_pD3DDev->CreateVertexShader( dwIndexedVertexDecl[i], 1565: (DWORD*)pCode->GetBufferPointer(), 1566: &(m_dwIndexedVertexShader[i]) , bUseSW ? D3DUSAGE_SOFTWAREPROCESSING : 0 ) ) ) 1567: return hr; 1568: 1569: pCode->Release(); 1570: } 1571: 1572: return S_OK; 1573: } 1574: //----------------------------------------------------------------------------- 1575: // ロード 1576: //----------------------------------------------------------------------------- 1577: HRESULT CSkinModel::Load( const TCHAR *filename ) 1578: { 1579: HRESULT hr; 1580: 1581: strcpy(m_szPath, filename); 1582: 1583: // メッシュのロード 1584: if(FAILED(hr = this->_LoadMeshHierarchy(m_pD3DDev))) return hr; 1585: 1586: // SetRenderState の設定 1587: if (FAILED(hr = RestoreDeviceObjects(m_pD3DDev))) return hr; 1588: 1589: return S_OK; 1590: } 1591: //----------------------------------------------------------------------------- 1592: // 射影行列の設定 1593: //----------------------------------------------------------------------------- 1594: HRESULT CSkinModel::_SetProjectionMatrix() 1595: { 1596: D3DXMATRIX mat; 1597: 1598: if (m_pdeMesh == NULL) return S_OK; 1599: 1600: FLOAT fAspect = m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height; 1601: D3DXMatrixPerspectiveFovRH(&mat, 0.25f*3.141592654f, fAspect, m_pdeMesh->fRadius / 64, m_pdeMesh->fRadius * 200); 1602: 1603: // ソフトウェアT&Lのために設定する 1604: HRESULT hr = m_pD3DDev->SetTransform( D3DTS_PROJECTION, (D3DMATRIX*)&mat ); 1605: if (FAILED(hr)) return hr; 1606: 1607: // ハードウェアT&Lのために設定する 1608: D3DXMatrixTranspose(&mat, &mat); 1609: return m_pD3DDev->SetVertexShaderConstant(2, &mat, 4); // c2~c5 1610: } 1611: //----------------------------------------------------------------------------- 1612: // シーンの初期化 1613: //----------------------------------------------------------------------------- 1614: HRESULT CSkinModel::RestoreDeviceObjects(LPDIRECT3DDEVICE8 pD3DDev) 1615: { 1616: HRESULT hr = S_OK; 1617: D3DLIGHT8 light; 1618: 1619: // レンダリングのための状態の設定 1620: pD3DDev->SetRenderState( D3DRS_DITHERENABLE, TRUE ); 1621: pD3DDev->SetRenderState( D3DRS_ZENABLE, TRUE ); 1622: pD3DDev->SetRenderState( D3DRS_SPECULARENABLE, FALSE ); 1623: pD3DDev->SetRenderState( D3DRS_NORMALIZENORMALS, TRUE ); 1624: 1625: pD3DDev->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW ); 1626: pD3DDev->SetRenderState( D3DRS_LIGHTING, TRUE ); 1627: pD3DDev->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR ); 1628: pD3DDev->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR ); 1629: 1630: pD3DDev->SetRenderState( D3DRS_COLORVERTEX, FALSE ); 1631: 1632: if (m_pdeMesh != NULL) _SetProjectionMatrix(); 1633: 1634: 1635: // ソフトウェアT&Lのためのライトの設定 1636: ZeroMemory( &light, sizeof(light) ); 1637: light.Type = D3DLIGHT_DIRECTIONAL; 1638: light.Diffuse.r = 1.0; 1639: light.Diffuse.g = 1.0; 1640: light.Diffuse.b = 1.0; 1641: light.Specular.r = 0; 1642: light.Specular.g = 0; 1643: light.Specular.b = 0; 1644: light.Ambient.r = 0.25; 1645: light.Ambient.g = 0.25; 1646: light.Ambient.b = 0.25; 1647: light.Direction = D3DXVECTOR3( 0.0f, 0.0f, -1.0f); 1648: 1649: if (FAILED(hr = pD3DDev->SetLight(0, &light ))) return E_FAIL; 1650: if (FAILED(hr = pD3DDev->LightEnable(0, TRUE))) return E_FAIL; 1651: 1652: // 頂点シェーダーのライトの設定 1653: pD3DDev->SetVertexShaderConstant(1, &D3DXVECTOR4( 0.0f, 0.0f, 1.0f, 0.0f ), 1); 1654: 1655: return S_OK; 1656: } 1657: 1658: //----------------------------------------------------------------------------- 1659: // 動かす 1660: //----------------------------------------------------------------------------- 1661: HRESULT CSkinModel::FrameMove(DWORD time) 1662: { 1663: if(m_pdeMesh){ 1664: m_pdeMesh->fCurTime = 4.8f*(float)(time - m_1st_time);// 時間の設定 1665: 1666: // 登録された全てのアニメに関して設定 1667: for (SFrame* pFrame = m_pdeMesh->pframeAnimHead; pFrame ; pFrame=pFrame->pframeAnimNext) { 1668: pFrame->SetTime(m_pdeMesh->fCurTime); 1669: } 1670: } 1671: 1672: return S_OK; 1673: } 1674: //----------------------------------------------------------------------------- 1675: // 行列の生成 1676: //----------------------------------------------------------------------------- 1677: HRESULT SFrame::UpdateFrames(D3DXMATRIX &matCur) 1678: { 1679: HRESULT hr = S_OK; 1680: this->matCombined = matCur; 1681: D3DXMatrixMultiply(&this->matCombined, &this->matRot, &matCur); 1682: D3DXMatrixMultiply(&this->matCombined, &this->matCombined, &this->matTrans ); 1683: 1684: // 自分の行列を親として、子供たちを次々に行列変換する 1685: for( SFrame *p=this->pframeFirstChild ; p!=NULL ; p=p->pframeSibling ){ 1686: if (FAILED(hr = p->UpdateFrames(this->matCombined))) return hr; 1687: } 1688: 1689: return S_OK; 1690: } 1691: //----------------------------------------------------------------------------- 1692: // スキンモデルでない物の描画 1693: //----------------------------------------------------------------------------- 1694: HRESULT CSkinModel::_DrawMeshContainerNoSkin(SMeshContainer *pmcMesh) 1695: { 1696: HRESULT hr; 1697: 1698: for (UINT it = 0; it < pmcMesh->cpattr; it++) { 1699: m_pD3DDev->SetMaterial(&(pmcMesh->rgMaterials[it])); 1700: m_pD3DDev->SetTexture(0, pmcMesh->pTextures[it]); 1701: if(FAILED(hr = pmcMesh->pMesh->DrawSubset( it ))) return hr; 1702: } 1703: 1704: return S_OK; 1705: } 1706: 1707: //----------------------------------------------------------------------------- 1708: // D3DNONINDEXED 1709: //----------------------------------------------------------------------------- 1710: HRESULT CSkinModel::_DrawMeshContainerNonIndexed(SMeshContainer *pmcMesh) 1711: { 1712: UINT ipattr; 1713: LPDIRECT3DDEVICE8 pD3DDev = m_pD3DDev; 1714: LPD3DXBONECOMBINATION pBoneComb; 1715: DWORD AttribIdPrev; 1716: HRESULT hr; 1717: 1718: AttribIdPrev = UNUSED32; 1719: pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pmcMesh->m_pBoneCombinationBuf->GetBufferPointer()); 1720: // Draw using default vtx processing of the device (typically HW) 1721: for (ipattr = 0; ipattr < pmcMesh->cpattr; ipattr++) { 1722: DWORD numBlend = 0; 1723: for (DWORD i = 0; i < pmcMesh->m_maxFaceInfl; ++i) { 1724: if (pBoneComb[ipattr].BoneId[i] != UINT_MAX) { 1725: numBlend = i; 1726: } 1727: } 1728: 1729: if (m_d3dCaps.MaxVertexBlendMatrices >= numBlend + 1) { 1730: for (DWORD i = 0; i < pmcMesh->m_maxFaceInfl; ++i) { 1731: DWORD matid = pBoneComb[ipattr].BoneId[i]; 1732: if (matid != UINT_MAX) { 1733: m_pD3DDev->SetTransform(D3DTS_WORLDMATRIX(i), pmcMesh->m_pBoneMatrix[matid]); 1734: m_pD3DDev->MultiplyTransform(D3DTS_WORLDMATRIX(i), &pmcMesh->m_pBoneOffsetMat[matid]); 1735: } 1736: } 1737: 1738: m_pD3DDev->SetRenderState(D3DRS_VERTEXBLEND, numBlend); 1739: 1740: if ((AttribIdPrev != pBoneComb[ipattr].AttribId) || (AttribIdPrev == UNUSED32)) { 1741: m_pD3DDev->SetMaterial(&(pmcMesh->rgMaterials[pBoneComb[ipattr].AttribId])); 1742: m_pD3DDev->SetTexture(0, pmcMesh->pTextures[pBoneComb[ipattr].AttribId]); 1743: AttribIdPrev = pBoneComb[ipattr].AttribId; 1744: } 1745: 1746: hr = pmcMesh->pMesh->DrawSubset( ipattr ); 1747: if(FAILED(hr)) return hr; 1748: } 1749: } 1750: 1751: // If necessary, draw parts that HW could not handle using SW 1752: if (pmcMesh->iAttrSplit < pmcMesh->cpattr) { 1753: AttribIdPrev = UNUSED32; 1754: m_pD3DDev->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, TRUE); 1755: for (ipattr = pmcMesh->iAttrSplit; ipattr < pmcMesh->cpattr; ipattr++) { 1756: DWORD numBlend = 0; 1757: for (DWORD i = 0; i < pmcMesh->m_maxFaceInfl; ++i) { 1758: if (pBoneComb[ipattr].BoneId[i] != UINT_MAX) { 1759: numBlend = i; 1760: } 1761: } 1762: 1763: if (m_d3dCaps.MaxVertexBlendMatrices < numBlend + 1) { 1764: for (DWORD i = 0; i < pmcMesh->m_maxFaceInfl; ++i) { 1765: DWORD matid = pBoneComb[ipattr].BoneId[i]; 1766: if (matid != UINT_MAX) { 1767: m_pD3DDev->SetTransform(D3DTS_WORLDMATRIX(i), pmcMesh->m_pBoneMatrix[matid]); 1768: m_pD3DDev->MultiplyTransform(D3DTS_WORLDMATRIX(i), &pmcMesh->m_pBoneOffsetMat[matid]); 1769: } 1770: } 1771: 1772: m_pD3DDev->SetRenderState(D3DRS_VERTEXBLEND, numBlend); 1773: 1774: if ((AttribIdPrev != pBoneComb[ipattr].AttribId) || (AttribIdPrev == UNUSED32)) { 1775: m_pD3DDev->SetMaterial(&(pmcMesh->rgMaterials[pBoneComb[ipattr].AttribId])); 1776: m_pD3DDev->SetTexture(0, pmcMesh->pTextures[pBoneComb[ipattr].AttribId]); 1777: AttribIdPrev = pBoneComb[ipattr].AttribId; 1778: } 1779: 1780: hr = pmcMesh->pMesh->DrawSubset( ipattr ); 1781: if(FAILED(hr)) return hr; 1782: } 1783: } 1784: m_pD3DDev->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, FALSE); 1785: } 1786: m_pD3DDev->SetRenderState(D3DRS_VERTEXBLEND, 0); 1787: 1788: return S_OK; 1789: } 1790: 1791: //----------------------------------------------------------------------------- 1792: // D3DINDEXEDVS 1793: //----------------------------------------------------------------------------- 1794: HRESULT CSkinModel::_DrawMeshContainerIndexedVs(SMeshContainer *pmcMesh) 1795: { 1796: UINT ipattr; 1797: LPDIRECT3DDEVICE8 pD3DDev = m_pD3DDev; 1798: LPD3DXBONECOMBINATION pBoneComb; 1799: HRESULT hr; 1800: 1801: D3DXVECTOR4 vConst( 1.0f, 0.0f, 0.0f, 765.01f ); 1802: LPDIRECT3DVERTEXBUFFER8 pVB; 1803: LPDIRECT3DINDEXBUFFER8 pIB; 1804: 1805: if (pmcMesh->m_bUseSW) {// 描画できない時はソフトウェアT&Lで描画 1806: m_pD3DDev->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, TRUE); 1807: } 1808: 1809: // 頂点、インデックスバッファの設定 1810: pmcMesh->pMesh->GetVertexBuffer(&pVB); 1811: pmcMesh->pMesh->GetIndexBuffer(&pIB); 1812: if(FAILED(hr = m_pD3DDev->SetStreamSource(0, pVB, D3DXGetFVFVertexSize(pmcMesh->pMesh->GetFVF()))))return hr; 1813: if(FAILED(hr = m_pD3DDev->SetIndices(pIB, 0)))return hr; 1814: pVB->Release(); 1815: pIB->Release(); 1816: 1817: // 混ぜている行列の個数に応じて、シェーダーを切り替える 1818: if(FAILED(hr = m_pD3DDev->SetVertexShader(m_dwIndexedVertexShader[pmcMesh->m_maxFaceInfl - 1])))return hr; 1819: 1820: pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pmcMesh->m_pBoneCombinationBuf->GetBufferPointer()); 1821: for (ipattr = 0; ipattr < pmcMesh->cpattr; ipattr++){ 1822: // ビュー行列をかけて、ボーンの行列を設定する 1823: for (DWORD i = 0; i < pmcMesh->m_paletteSize; ++i){ 1824: DWORD matid = pBoneComb[ipattr].BoneId[i]; 1825: if (matid != UINT_MAX){ 1826: D3DXMATRIXA16 mat; 1827: D3DXMatrixMultiply(&mat, &pmcMesh->m_pBoneOffsetMat[matid], pmcMesh->m_pBoneMatrix[matid]); 1828: D3DXMatrixMultiplyTranspose(&mat, &mat, &m_View); 1829: m_pD3DDev->SetVertexShaderConstant(i*3 + 9, &mat, 3); 1830: } 1831: } 1832: 1833: // 質感の設定 1834: D3DXCOLOR ambEmm; 1835: D3DMATERIAL8 *pMaterial = &pmcMesh->rgMaterials[pBoneComb[ipattr].AttribId]; 1836: D3DXColorModulate(&ambEmm, &D3DXCOLOR(pMaterial->Ambient),&D3DXCOLOR(.25, .25, .25, 1.0)); 1837: ambEmm += D3DXCOLOR(pMaterial->Emissive); 1838: m_pD3DDev->SetVertexShaderConstant(8, &(pMaterial->Diffuse), 1);// 平行光源 1839: m_pD3DDev->SetVertexShaderConstant(7, &ambEmm, 1); // 環境光 1840: vConst.y = pMaterial->Power; 1841: m_pD3DDev->SetVertexShaderConstant(0, &vConst, 1);// すぺきゅらー 1842: // テクスチャーの設定 1843: m_pD3DDev->SetTexture(0, pmcMesh->pTextures[pBoneComb[ipattr].AttribId]); 1844: // 実際の描画 1845: hr = m_pD3DDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 1846: pBoneComb[ipattr].VertexStart, pBoneComb[ipattr].VertexCount, 1847: pBoneComb[ipattr].FaceStart * 3, pBoneComb[ipattr].FaceCount); 1848: if(FAILED(hr)) return hr; 1849: } 1850: 1851: // ソフトウェアT&Lの時を戻す 1852: if (pmcMesh->m_bUseSW) { 1853: m_pD3DDev->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, FALSE); 1854: } 1855: 1856: return S_OK; 1857: } 1858: 1859: //----------------------------------------------------------------------------- 1860: // D3DINDEXED 1861: //----------------------------------------------------------------------------- 1862: HRESULT CSkinModel::_DrawMeshContainerIndexed(SMeshContainer *pmcMesh) 1863: { 1864: UINT ipattr; 1865: LPDIRECT3DDEVICE8 pD3DDev = m_pD3DDev; 1866: LPD3DXBONECOMBINATION pBoneComb; 1867: HRESULT hr; 1868: 1869: if (pmcMesh->m_bUseSW) { 1870: pD3DDev->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, TRUE); 1871: } 1872: 1873: if (pmcMesh->m_maxFaceInfl == 1){ 1874: pD3DDev->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_0WEIGHTS); 1875: }else{ 1876: pD3DDev->SetRenderState(D3DRS_VERTEXBLEND, pmcMesh->m_maxFaceInfl - 1); 1877: } 1878: if (pmcMesh->m_maxFaceInfl) pD3DDev->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, TRUE); 1879: pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pmcMesh->m_pBoneCombinationBuf->GetBufferPointer()); 1880: for (ipattr = 0; ipattr < pmcMesh->cpattr; ipattr++) { 1881: for (DWORD i = 0; i < pmcMesh->m_paletteSize; ++i) { 1882: DWORD matid = pBoneComb[ipattr].BoneId[i]; 1883: if (matid != UINT_MAX) { 1884: pD3DDev->SetTransform(D3DTS_WORLDMATRIX(i), pmcMesh->m_pBoneMatrix[matid]); 1885: pD3DDev->MultiplyTransform(D3DTS_WORLDMATRIX(i), &pmcMesh->m_pBoneOffsetMat[matid]); 1886: } 1887: } 1888: 1889: pD3DDev->SetMaterial(&(pmcMesh->rgMaterials[pBoneComb[ipattr].AttribId])); 1890: pD3DDev->SetTexture(0, pmcMesh->pTextures[pBoneComb[ipattr].AttribId]); 1891: 1892: if(FAILED(hr = pmcMesh->pMesh->DrawSubset( ipattr )))return hr; 1893: } 1894: pD3DDev->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE); 1895: pD3DDev->SetRenderState(D3DRS_VERTEXBLEND, 0); 1896: 1897: if (pmcMesh->m_bUseSW) { 1898: pD3DDev->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, FALSE); 1899: } 1900: 1901: return S_OK; 1902: } 1903: //----------------------------------------------------------------------------- 1904: // SOFTWARE 1905: //----------------------------------------------------------------------------- 1906: HRESULT CSkinModel::_DrawMeshContainerSoftware(SMeshContainer *pmcMesh) 1907: { 1908: D3DXMATRIX Identity; 1909: DWORD cBones = pmcMesh->m_pSkinMesh->GetNumBones(); 1910: HRESULT hr; 1911: 1912: // ボーンの行列を設定する 1913: for (DWORD i = 0; i < cBones; ++i){ 1914: D3DXMatrixMultiply (&m_pBoneMatrices[i],&pmcMesh->m_pBoneOffsetMat[i], pmcMesh->m_pBoneMatrix[i]); 1915: } 1916: 1917: // ワールド座標を設定する 1918: D3DXMatrixIdentity(&Identity); 1919: if (FAILED(hr = m_pD3DDev->SetTransform(D3DTS_WORLD, &Identity))) return hr; 1920: 1921: // スキン構造を作成する 1922: if (FAILED(hr = pmcMesh->m_pSkinMesh->UpdateSkinnedMesh(m_pBoneMatrices, NULL, pmcMesh->pMesh)))return hr; 1923: 1924: // 属性やテクスチャーを設定して実際に描画 1925: for (unsigned long ipattr = 0; ipattr < pmcMesh->cpattr; ipattr++) { 1926: int id = pmcMesh->m_pAttrTable[ipattr].AttribId; 1927: m_pD3DDev->SetMaterial(&(pmcMesh->rgMaterials[id])); 1928: m_pD3DDev->SetTexture(0, pmcMesh->pTextures[id]); 1929: if (FAILED(hr=pmcMesh->pMesh->DrawSubset(id))) return hr; 1930: } 1931: 1932: return S_OK; 1933: } 1934: //----------------------------------------------------------------------------- 1935: // 各メッシュの描画 1936: //----------------------------------------------------------------------------- 1937: HRESULT CSkinModel::_DrawMeshContainer(SMeshContainer *pmcMesh) 1938: { 1939: HRESULT hr = S_OK; 1940: 1941: // スキンじゃないモデル 1942: if (! pmcMesh->m_pSkinMesh) return _DrawMeshContainerNoSkin(pmcMesh); 1943: 1944: // 描画方法が切り変わったらメッシュを生成しなおす 1945: if (m_method != pmcMesh->m_Method) this->GenerateMesh(pmcMesh); 1946: 1947: // それぞれの手法に応じてそれぞれ描画 1948: if (m_method == D3DNONINDEXED) return _DrawMeshContainerNonIndexed(pmcMesh); 1949: if (m_method == D3DINDEXEDVS ) return _DrawMeshContainerIndexedVs (pmcMesh); 1950: if (m_method == D3DINDEXED ) return _DrawMeshContainerIndexed (pmcMesh); 1951: if (m_method == SOFTWARE ) return _DrawMeshContainerSoftware (pmcMesh); 1952: 1953: return S_OK; 1954: } 1955: //----------------------------------------------------------------------------- 1956: // メッシュの描画 1957: //----------------------------------------------------------------------------- 1958: HRESULT CSkinModel::_DrawFrames(SFrame *pframe, UINT &cTriangles) 1959: { 1960: HRESULT hr = S_OK; 1961: LPDIRECT3DDEVICE8 pD3DDev = m_pD3DDev; 1962: 1963: // ワールド行列の生成 1964: if (pframe->pmcMesh != NULL){ 1965: hr = pD3DDev->SetTransform(D3DTS_WORLD, &pframe->matCombined); 1966: if(FAILED(hr)) return hr; 1967: } 1968: // 登録されているメッシュを表示 1969: for(SMeshContainer *it=pframe->pmcMesh ; it ; it=it->pmcNext){ 1970: if (FAILED(hr = _DrawMeshContainer(it)))return hr; 1971: cTriangles += it->pMesh->GetNumFaces(); 1972: } 1973: // 子供を次々に表示 1974: for(SFrame *pChild=pframe->pframeFirstChild ; pChild ; pChild=pChild->pframeSibling){ 1975: if (FAILED(hr = _DrawFrames(pChild, cTriangles))) return hr; 1976: } 1977: 1978: return S_OK; 1979: } 1980: //----------------------------------------------------------------------------- 1981: // 描画 1982: //----------------------------------------------------------------------------- 1983: HRESULT CSkinModel::Render() 1984: { 1985: UINT cTriangles = 0; 1986: HRESULT hr; 1987: 1988: if(m_pdeMesh){ 1989: // 視点を設定する 1990: m_pdeMesh->pframeRoot->matRot = m_Rot; 1991: m_pdeMesh->pframeRoot->matTrans = m_Trans; 1992: 1993: // ソフトウェアT&Lのためにビュー行列を設定 1994: hr = m_pD3DDev->SetTransform(D3DTS_VIEW, (D3DMATRIX*)&m_View); 1995: if(FAILED(hr)) return hr; 1996: 1997: D3DXMATRIXA16 mCur; 1998: D3DXMatrixIdentity(&mCur); 1999: // 動かす 2000: if (FAILED(hr = m_pdeMesh->pframeRoot->UpdateFrames(mCur))) return hr; 2001: // 描画する 2002: if (FAILED(hr = _DrawFrames(m_pdeMesh->pframeRoot, cTriangles))) return hr; 2003: } 2004: 2005: return S_OK; 2006: } 2007: //----------------------------------------------------------------------------- 2008: // 最後の時やデバイスが変更されたとき等に呼ばれる 2009: //----------------------------------------------------------------------------- 2010: HRESULT CSkinModel::Release() 2011: { 2012: _InvalidateDeviceObjects(); 2013: _DeleteDeviceObjects(); 2014: 2015: return S_OK; 2016: } 2017: //----------------------------------------------------------------------------- 2018: // 最後の時やデバイスが変更されたとき等に呼ばれる 2019: //----------------------------------------------------------------------------- 2020: HRESULT CSkinModel::_InvalidateDeviceObjects() 2021: { 2022: if(m_pdeMesh) m_pdeMesh->pframeRoot->ReleaseDeviceDependentMeshes(); 2023: 2024: return S_OK; 2025: } 2026: //----------------------------------------------------------------------------- 2027: // 最後の時やデバイスが変更されたとき等に呼ばれる 2028: //----------------------------------------------------------------------------- 2029: HRESULT CSkinModel::_DeleteDeviceObjects() 2030: { 2031: if(m_pdeMesh) delete m_pdeMesh; m_pdeMesh = NULL; 2032: 2033: delete [] m_pBoneMatrices; 2034: 2035: return S_OK; 2036: } 2037: //----------------------------------------------------------------------------- 2038: // メッシュとして確保したメモリを開放する 2039: //----------------------------------------------------------------------------- 2040: void SFrame::ReleaseDeviceDependentMeshes() 2041: { 2042: if (this->pmcMesh != NULL){ 2043: for (SMeshContainer* pmcCurr = this->pmcMesh; pmcCurr != NULL; pmcCurr = pmcCurr->pmcNext){ 2044: if (pmcCurr->m_pSkinMesh != NULL){ 2045: RELEASE(pmcCurr->pMesh); 2046: 2047: pmcCurr->m_Method = NONE; 2048: } 2049: } 2050: } 2051: 2052: // 子供や子供兄弟を次々に削除 2053: if (this->pframeFirstChild != NULL) 2054: this->pframeFirstChild->ReleaseDeviceDependentMeshes(); 2055: 2056: if (this->pframeSibling != NULL) 2057: this->pframeSibling->ReleaseDeviceDependentMeshes(); 2058: } 2059: //----------------------------------------------------------------------------- 2060: // 現在選択されているメッシュの削除 2061: //----------------------------------------------------------------------------- 2062: HRESULT CSkinModel::_DeleteSelectedMesh() 2063: { 2064: if (m_pdeMesh != NULL) { 2065: delete m_pdeMesh; 2066: m_pdeMesh = NULL; 2067: } 2068: 2069: return S_OK; 2070: } 2071: