//! 初期化。 bool Create(Device& device, const TCHAR* pmdPath, const TCHAR* vmdPath) { // モデルデータの読み込み。 MMD::PMD pmd; if (failed(LoadPMD(pmd, pmdPath))) return false; static TCHAR dirPath[256]; GetDirectoryPath(pmdPath, dirPath, _countof(dirPath)); // メッシュの頂点情報のコピー。 std::vector<MyRenderer::ShaderInput> meshVertices; meshVertices.resize(pmd.vert_count); for (unsigned int i = 0; i < pmd.vert_count; ++i) { meshVertices[i].position = ToD3DXVECTOR3(pmd.vertex[i].pos); meshVertices[i].uv = ToD3DXVECTOR2(pmd.vertex[i].uv); } // インデックスバッファを作成する。 _indexBuffer = device.CreateIndexBuffer(D3D10_USAGE_IMMUTABLE, 0, sizeof(unsigned short), pmd.face_vert_count, &pmd.face_vert_index[0]); if (_indexBuffer == IndexBufferHandle::INVALID) return false; _numIndices = pmd.face_vert_count; // マテリアル情報の解析。 _drawPlans.push_back(DrawPlan()); DrawPlan* pPlan = &_drawPlans.back(); pPlan->_shader = -1; pPlan->_startIndex = 0; pPlan->_texture = -1; unsigned int total = 0; for (unsigned int i = 0, k = 0; i < pmd.material_count; ++i) { MMD::PMD::Material& material = pmd.material[i]; // マテリアルの対応する頂点にカラーを設定する。 total += material.face_vert_count; for (; k < total; ++k) { MyRenderer::ShaderInput& vertex = meshVertices[pmd.face_vert_index[k]]; vertex.color[0] = material.diffuse_color[0]; vertex.color[1] = material.diffuse_color[1]; vertex.color[2] = material.diffuse_color[2]; } // テクスチャありなしで描画プランを分ける。 int shader = MyRenderer::PMD_DEFAULT; int textureIndex = -1; if (strlen(material.texture_file_name) > 0) { shader = MyRenderer::PMD_TEXTURE; // テクスチャを読み込む。 TString fileName; StringToTString(material.texture_file_name, fileName); TString texPath = dirPath; texPath += fileName; DEBUG_TRACE(texPath.c_str()); TextureHandle tex = device.CreateTextureFromFile(texPath.c_str()); if (tex == TextureHandle::INVALID) return false; _textures.push_back(tex); textureIndex = static_cast<int>(_textures.size() - 1); } if (pPlan->_shader < 0) { pPlan->_shader = shader; } else if (pPlan->_shader != shader || pPlan->_texture != textureIndex) { _drawPlans.push_back(*pPlan); pPlan = &_drawPlans.back(); pPlan->_shader = shader; pPlan->_startIndex = pPlan->_startIndex + pPlan->_numIndices; pPlan->_numIndices = 0; } pPlan->_numIndices += material.face_vert_count; pPlan->_texture = textureIndex; } // メッシュの頂点バッファ作成。 _meshVertexBuffer = device.CreateVertexBuffer(D3D10_USAGE_IMMUTABLE, 0, sizeof(MyRenderer::ShaderInput), meshVertices.size(), &meshVertices[0]); if (_meshVertexBuffer == VertexBufferHandle::INVALID) return false; // ボーンの解析。 _drawBoneVertices.resize(pmd.bone_count); std::vector<unsigned short> drawBoneIndices; drawBoneIndices.reserve(pmd.bone_count*2); unsigned short k = 0; for (unsigned int i = 0; i < pmd.bone_count; ++i) { MMD::PMD::Bone& boneHead = pmd.bone[i]; // ボーン情報の登録。 BoneInfo boneInfo; boneInfo._name = boneHead.bone_name; Vector3 headPosParentSpace; if (boneHead.parent_bone_index != MMD::PMD::Bone::INVALID_PARENT) { // 親ボーンに子ボーンを登録。 MMD::PMD::Bone& boneParent = pmd.bone[boneHead.parent_bone_index]; BoneNameIndexMap::iterator found = _boneNameIndexMap.find(boneParent.bone_name); if (found == _boneNameIndexMap.end()) continue; // あるとめんどくさい…。 _bones[found->second]._childs.push_back(i); headPosParentSpace = boneHead.bone_head_pos - boneParent.bone_head_pos; } else { headPosParentSpace = boneHead.bone_head_pos; _rootBoneIndices.push_back(i); } D3DXMatrixTranslation(&boneInfo._transformToParentSpace, headPosParentSpace.x, headPosParentSpace.y, headPosParentSpace.z); D3DXMatrixIdentity(&boneInfo._transformLocalSpace); boneInfo._transformFixModelSpace = boneInfo._transformLocalSpace; _bones.push_back(boneInfo); _boneNameIndexMap.insert(std::make_pair(boneHead.bone_name, i)); // 描画用頂点のセットアップ。 MyRenderer::ShaderInput vertexHead; vertexHead.position = ToD3DXVECTOR3(boneHead.bone_head_pos); Color::WHITE.ToFloat3(vertexHead.color); vertexHead.uv = D3DXVECTOR2(0.f, 0.f); _drawBoneVertices[i] = vertexHead; if (boneHead.tail_pos_bone_index != MMD::PMD::Bone::INVALID_TAIL) { drawBoneIndices.push_back(i); drawBoneIndices.push_back(boneHead.tail_pos_bone_index); } } // end for (unsigned int i = 0; ...) _drawBoneVertexBuffer = device.CreateVertexBuffer(D3D10_USAGE_DEFAULT, 0, sizeof(MyRenderer::ShaderInput), _drawBoneVertices.size(), &_drawBoneVertices[0]); if (_drawBoneVertexBuffer == VertexBufferHandle::INVALID) return false; _numDrawBoneVertices = static_cast<unsigned int>(drawBoneIndices.size()); _drawBoneIndexBuffer = device.CreateIndexBuffer(D3D10_USAGE_IMMUTABLE, 0, sizeof(unsigned short), _numDrawBoneVertices, &drawBoneIndices[0]); if (_drawBoneIndexBuffer == IndexBufferHandle::INVALID) return false; // モーションデータの読み込み。対応するボーンごとに整理しておく。 MMD::VMD vmd; if (failed(LoadVMD(vmd, vmdPath))) return false; _allBoneKeyFrames.resize(pmd.bone_count); _keyFrameMax = 0; for (unsigned int i = 0; i < vmd.motion_count; ++i) { MMD::VMD::Motion& motion = vmd.motion[i]; BoneNameIndexMap::iterator found = _boneNameIndexMap.find(motion.BoneName); if (found != _boneNameIndexMap.end()) { BoneKeyFrames& keyFrames = _allBoneKeyFrames[found->second]; BoneKeyFrame keyFrame; keyFrame._frame = motion.Frame; keyFrame._time = motion.Frame * MOTION_FPS; keyFrame._translation = ToD3DXVECTOR3(motion.Location); keyFrame._rotation = *reinterpret_cast<D3DXQUATERNION*>(motion.Rotation); keyFrame._interpolation_x.p1 = D3DXVECTOR2(motion.Interpolation[0], motion.Interpolation[4]); keyFrame._interpolation_x.p2 = D3DXVECTOR2(motion.Interpolation[8], motion.Interpolation[12]); keyFrame._interpolation_y.p1 = D3DXVECTOR2(motion.Interpolation[1], motion.Interpolation[5]); keyFrame._interpolation_y.p2 = D3DXVECTOR2(motion.Interpolation[9], motion.Interpolation[13]); keyFrame._interpolation_z.p1 = D3DXVECTOR2(motion.Interpolation[2], motion.Interpolation[6]); keyFrame._interpolation_z.p2 = D3DXVECTOR2(motion.Interpolation[10], motion.Interpolation[14]); keyFrame._interpolation_r.p1 = D3DXVECTOR2(motion.Interpolation[3], motion.Interpolation[7]); keyFrame._interpolation_r.p2 = D3DXVECTOR2(motion.Interpolation[11], motion.Interpolation[15]); keyFrames.insert(std::make_pair(motion.Frame, keyFrame)); if (_keyFrameMax < motion.Frame) _keyFrameMax = motion.Frame; } #if defined(_DEBUG) TString bone_name; StringToTString(motion.BoneName, bone_name); DEBUG_TRACE(_T("Bone[%u] : name=%s, frame=%u, trans=(%.2f, %.2f, %.2f), rot=(%.2f, %.2f, %.2f, %.2f)"), i, bone_name.c_str(), motion.Frame, motion.Location.x, motion.Location.y, motion.Location.z, motion.Rotation[0], motion.Rotation[1], motion.Rotation[2], motion.Rotation[3]); #endif } SwitchToLinearInterpolation(); // サンプラ。 D3D10_SAMPLER_DESC sampDesc; sampDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_POINT; sampDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; sampDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; sampDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; sampDesc.MipLODBias = 0.0f; sampDesc.MaxAnisotropy = 16; sampDesc.ComparisonFunc = D3D10_COMPARISON_NEVER; sampDesc.BorderColor[0] = 0.f; sampDesc.BorderColor[1] = 0.f; sampDesc.BorderColor[2] = 0.f; sampDesc.BorderColor[3] = 0.f; sampDesc.MinLOD = 0.f; sampDesc.MaxLOD = FLT_MAX; _sampler = device.CreateSamplerState(sampDesc); if (_sampler == SamplerStateHandle::INVALID) return false; return true; }
bool Create(Device& device, const TCHAR* filePath) { MMD::PMD pmd; if (failed(LoadPMD(pmd, filePath))) return false; static TCHAR dirPath[256]; GetDirectoryPath(filePath, dirPath, _countof(dirPath)); // メッシュの頂点情報のコピー。 std::vector<MyRenderer::ShaderInput> vertices; vertices.resize(pmd.vert_count); for (unsigned int i = 0; i < pmd.vert_count; ++i) { vertices[i].position = ToD3DXVECTOR3(pmd.vertex[i].pos); vertices[i].uv = ToD3DXVECTOR2(pmd.vertex[i].uv); } // インデックスバッファを作成する。 _indices = device.CreateIndexBuffer(D3D10_USAGE_IMMUTABLE, 0, sizeof(unsigned short), pmd.face_vert_count, &pmd.face_vert_index[0]); if (_indices == IndexBufferHandle::INVALID) return false; _numIndices = pmd.face_vert_count; // マテリアル情報の解析。 _drawPlans.push_back(DrawPlan()); DrawPlan* pPlan = &_drawPlans.back(); pPlan->_shader = -1; pPlan->_startIndex = 0; pPlan->_texture = -1; unsigned int total = 0; for (unsigned int i = 0, k = 0; i < pmd.material_count; ++i) { MMD::PMD::Material& material = pmd.material[i]; // マテリアルの対応する頂点にカラーを設定する。 total += material.face_vert_count; for (; k < total; ++k) { MyRenderer::ShaderInput& vertex = vertices[pmd.face_vert_index[k]]; vertex.color[0] = material.diffuse_color[0]; vertex.color[1] = material.diffuse_color[1]; vertex.color[2] = material.diffuse_color[2]; } // テクスチャありなしで描画プランを分ける。 int shader = MyRenderer::PMD_DEFAULT; int textureIndex = -1; if (strlen(material.texture_file_name) > 0) { shader = MyRenderer::PMD_TEXTURE; // テクスチャを読み込む。 static TCHAR fileName[256]; fileName[0] = 0; MultiByteToWideChar(CP_ACP, 0, material.texture_file_name, -1, fileName, _countof(fileName)); static TCHAR texPath[256]; _tcscpy_s(texPath, dirPath); _tcscat_s(texPath, fileName); DEBUG_TRACE(texPath); TextureHandle tex = device.CreateTextureFromFile(texPath); if (tex == TextureHandle::INVALID) return false; _textures.push_back(tex); textureIndex = static_cast<int>(_textures.size() - 1); } if (pPlan->_shader < 0) { pPlan->_shader = shader; } else if (pPlan->_shader != shader || pPlan->_texture != textureIndex) { _drawPlans.push_back(*pPlan); pPlan = &_drawPlans.back(); pPlan->_shader = shader; pPlan->_startIndex = pPlan->_startIndex + pPlan->_numIndices; pPlan->_numIndices = 0; } pPlan->_numIndices += material.face_vert_count; pPlan->_texture = textureIndex; } // メッシュの頂点バッファ作成。 _vertices = device.CreateVertexBuffer(D3D10_USAGE_IMMUTABLE, 0, sizeof(MyRenderer::ShaderInput), vertices.size(), &vertices[0]); if (_vertices == VertexBufferHandle::INVALID) return false; // ボーンを解析して描画用の頂点列を作る。 vertices.resize(0); for (unsigned i = 0; i < pmd.bone_count; ++i) { //if (i != 50) continue; MMD::PMD::Bone& bone = pmd.bone[i]; // if (bone.parent_bone_index == MMD::PMD::Bone::INVALID_PARENT) // continue; if (bone.tail_pos_bone_index == MMD::PMD::Bone::INVALID_TAIL) continue; MMD::PMD::Bone& boneTail = pmd.bone[bone.tail_pos_bone_index]; MyRenderer::ShaderInput boneFrom; boneFrom.position = ToD3DXVECTOR3(bone.bone_head_pos); Color::WHITE.ToFloat3(boneFrom.color); boneFrom.uv = D3DXVECTOR2(0.f, 0.f); MyRenderer::ShaderInput boneTo; boneTo.position = ToD3DXVECTOR3(boneTail.bone_head_pos); Color::GRAY.ToFloat3(boneTo.color); boneTo.uv = D3DXVECTOR2(0.f, 0.f); vertices.push_back(boneFrom); vertices.push_back(boneTo); } _numBones = pmd.bone_count; _bones = device.CreateVertexBuffer(D3D10_USAGE_IMMUTABLE, 0, sizeof(MyRenderer::ShaderInput), vertices.size(), &vertices[0]); if (_bones == VertexBufferHandle::INVALID) return false; // サンプラ。 D3D10_SAMPLER_DESC sampDesc; sampDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_POINT; sampDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; sampDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; sampDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; sampDesc.MipLODBias = 0.0f; sampDesc.MaxAnisotropy = 16; sampDesc.ComparisonFunc = D3D10_COMPARISON_NEVER; sampDesc.BorderColor[0] = 0.f; sampDesc.BorderColor[1] = 0.f; sampDesc.BorderColor[2] = 0.f; sampDesc.BorderColor[3] = 0.f; sampDesc.MinLOD = 0.f; sampDesc.MaxLOD = FLT_MAX; _sampler = device.CreateSamplerState(sampDesc); if (_sampler == SamplerStateHandle::INVALID) return false; return true; }