bool PMDHandler::doLoad(Model& model, istream& stream) noexcept { PMD _pmd; if (!stream.read((char*)&_pmd.Header, sizeof(_pmd.Header))) return false; // vertex if (!stream.read((char*)&_pmd.VertexCount, sizeof(_pmd.VertexCount))) return false; if (_pmd.VertexCount > 0) { _pmd.VertexList.resize(_pmd.VertexCount); if (!stream.read((char*)&_pmd.VertexList[0], (std::streamsize)(sizeof(PMD_Vertex)* _pmd.VertexCount))) return false; } // index if (!stream.read((char*)&_pmd.IndexCount, sizeof(_pmd.IndexCount))) return false; if (_pmd.IndexCount > 0) { _pmd.IndexList.resize(_pmd.IndexCount); if (!stream.read((char*)&_pmd.IndexList[0], (std::streamsize)(sizeof(PMD_Index)* _pmd.IndexCount))) return false; } // materal if (!stream.read((char*)&_pmd.MaterialCount, sizeof(_pmd.MaterialCount))) return false; if (_pmd.MaterialCount > 0) { _pmd.MaterialList.resize(_pmd.MaterialCount); if (!stream.read((char*)&_pmd.MaterialList[0], (std::streamsize)(sizeof(PMD_Material)* _pmd.MaterialCount))) return false; } // bone if (!stream.read((char*)&_pmd.BoneCount, sizeof(_pmd.BoneCount))) return false; if (_pmd.BoneCount > 0) { _pmd.BoneList.resize(_pmd.BoneCount); if (!stream.read((char*)&_pmd.BoneList[0], (std::streamsize)(sizeof(PMD_Bone)* _pmd.BoneCount))) return false; } // IK if (!stream.read((char*)&_pmd.IkCount, sizeof(_pmd.IkCount))) return false; if (_pmd.IkCount > 0) { _pmd.IkList.resize(_pmd.IkCount); for (std::size_t i = 0; i < (std::size_t)_pmd.IkCount; i++) { if (!stream.read((char*)&_pmd.IkList[i].IK, sizeof(_pmd.IkList[i].IK))) return false; if (!stream.read((char*)&_pmd.IkList[i].Target, sizeof(_pmd.IkList[i].Target))) return false; if (!stream.read((char*)&_pmd.IkList[i].LinkCount, sizeof(_pmd.IkList[i].LinkCount))) return false; if (!stream.read((char*)&_pmd.IkList[i].LoopCount, sizeof(_pmd.IkList[i].LoopCount))) return false; if (!stream.read((char*)&_pmd.IkList[i].LimitOnce, sizeof(_pmd.IkList[i].LimitOnce))) return false; _pmd.IkList[i].LinkList.resize(_pmd.IkList[i].LinkCount); if (!stream.read((char*)&_pmd.IkList[i].LinkList[0], (std::streamsize)(sizeof(PMD_Link)* _pmd.IkList[i].LinkCount))) return false; } } // Morph if (!stream.read((char*)&_pmd.MorphCount, sizeof(_pmd.MorphCount))) return false; if (_pmd.MorphCount > 0) { _pmd.MorphList.resize(_pmd.MorphCount); for (std::size_t i = 0; i < (std::size_t)_pmd.MorphCount; i++) { if (!stream.read((char*)&_pmd.MorphList[i].Name, sizeof(_pmd.MorphList[i].Name))) return false; if (!stream.read((char*)&_pmd.MorphList[i].VertexCount, sizeof(_pmd.MorphList[i].VertexCount))) return false; if (!stream.read((char*)&_pmd.MorphList[i].Category, sizeof(_pmd.MorphList[i].Category))) return false; if (_pmd.MorphList[i].VertexCount > 0) { _pmd.MorphList[i].VertexList.resize(_pmd.MorphList[i].VertexCount); if (!stream.read((char*)&_pmd.MorphList[i].VertexList[0], (std::streamsize)(sizeof(PMD_MorphVertex)* _pmd.MorphList[i].VertexCount))) return false; } } } // frame window if (!stream.read((char*)&_pmd.FrameWindow.ExpressionListCount, sizeof(_pmd.FrameWindow.ExpressionListCount))) return false; if (_pmd.FrameWindow.ExpressionListCount > 0) { _pmd.FrameWindow.ExpressionList.resize(_pmd.FrameWindow.ExpressionListCount); if (!stream.read((char*)&_pmd.FrameWindow.ExpressionList[0], (std::streamsize)(sizeof(PMD_Expression)* _pmd.FrameWindow.ExpressionListCount))) return false; } if (!stream.read((char*)&_pmd.FrameWindow.NodeNameCount, sizeof(_pmd.FrameWindow.NodeNameCount))) return false; if (_pmd.FrameWindow.NodeNameCount > 0) { _pmd.FrameWindow.NodeNameList.resize(_pmd.FrameWindow.NodeNameCount); if (!stream.read((char*)&_pmd.FrameWindow.NodeNameList[0].Name, (std::streamsize)(sizeof(PMD_NodeName)* _pmd.FrameWindow.NodeNameCount))) return false; } if (!stream.read((char*)&_pmd.FrameWindow.BoneToNodeCount, sizeof(_pmd.FrameWindow.BoneToNodeCount))) return false; if (_pmd.FrameWindow.BoneToNodeCount > 0) { _pmd.FrameWindow.BoneToNodeList.resize(_pmd.FrameWindow.BoneToNodeCount); if (!stream.read((char*)&_pmd.FrameWindow.BoneToNodeList[0].Bone, (std::streamsize)(sizeof(PMD_BoneToNode)* _pmd.FrameWindow.BoneToNodeCount))) return false; } // description if (!stream.read((char*)&_pmd.HasDescription, sizeof(_pmd.HasDescription))) return false; if (_pmd.HasDescription) { if (!stream.read((char*)&_pmd.Description.ModelName, sizeof(_pmd.Description.ModelName))) return false; if (!stream.read((char*)&_pmd.Description.Comment, sizeof(_pmd.Description.Comment))) return false; for (PMD_BoneCount i = 0; i < _pmd.BoneCount; i++) { PMD_BoneName name; if (!stream.read((char*)&name.Name, sizeof(name))) return false; _pmd.Description.BoneName.push_back(name); } for (PMD_uint8_t i = 0; i < _pmd.FrameWindow.ExpressionListCount; i++) { PMD_MorphName name; if (!stream.read((char*)&name.Name, sizeof(name))) return false; _pmd.Description.FaceName.push_back(name); } for (PMD_uint8_t i = 0; i < _pmd.FrameWindow.NodeNameCount; i++) { PMD_NodeName name; if (!stream.read((char*)&name.Name, sizeof(name))) return false; _pmd.Description.FrameName.push_back(name); } } // toon _pmd.ToonCount = PMD_NUM_TOON; _pmd.ToonList.resize(_pmd.ToonCount); if (!stream.read((char*)&_pmd.ToonList[0].Name, (std::streamsize)(sizeof(PMD_Toon) * _pmd.ToonCount))) return false; // rigidbody if (!stream.read((char*)&_pmd.BodyCount, sizeof(_pmd.BodyCount))) return false; if (_pmd.BodyCount > 0) { _pmd.BodyList.resize(_pmd.BodyCount); if (!stream.read((char*)&_pmd.BodyList[0], (std::streamsize)(sizeof(PMD_Body)* _pmd.BodyCount))) return false; } // joint if (!stream.read((char*)&_pmd.JointCount, sizeof(_pmd.JointCount))) return false; if (_pmd.JointCount > 0) { _pmd.JointList.resize(_pmd.JointCount); if (!stream.read((char*)&_pmd.JointList[0], (std::streamsize)(sizeof(PMD_Body)* _pmd.JointCount))) return false; } for (std::size_t index = 0; index < _pmd.MaterialList.size(); index++) { auto& it = _pmd.MaterialList[index]; auto material = std::make_shared<MaterialProperty>(); material->set(MATKEY_COLOR_DIFFUSE, it.Diffuse); material->set(MATKEY_COLOR_AMBIENT, it.Ambient); material->set(MATKEY_COLOR_SPECULAR, it.Specular); material->set(MATKEY_OPACITY, it.Opacity); material->set(MATKEY_SHININESS, it.Shininess); std::string name = it.TextureName; std::string::size_type substr = name.find_first_of("*"); if (substr != std::string::npos) { name.erase(name.begin() + substr, name.end()); } material->set(MATKEY_TEXTURE_DIFFUSE(0), name); material->set(MATKEY_TEXTURE_AMBIENT(0), name); model.addMaterial(material); } PMD_Index* indices = _pmd.IndexList.data(); PMD_Vertex* vertices = _pmd.VertexList.data(); MeshPropertyPtr root = std::make_shared<MeshProperty>(); MeshPropertyPtr mesh = root; MeshPropertyPtr last = nullptr; for (std::size_t index = 0; index < _pmd.MaterialList.size(); index++) { auto& it = _pmd.MaterialList[index]; Vector3Array points; Vector3Array normals; Vector2Array texcoords; VertexWeights weights; UintArray faces; for (PMD_IndexCount i = 0; i < it.FaceVertexCount; i++, indices++) { PMD_Vertex& v = vertices[*indices]; points.push_back(v.Position); normals.push_back(v.Normal); texcoords.push_back(v.UV); faces.push_back(i); VertexWeight weight; weight.weight1 = v.Weight / 100.0; weight.weight2 = 1.0 - weight.weight1; weight.weight3 = 0.0f; weight.weight4 = 0.0f; weight.bone1 = v.Bone.Bone1; weight.bone2 = v.Bone.Bone2; weight.bone3 = 0; weight.bone4 = 0; weights.push_back(weight); } if (last == mesh) { mesh = std::make_shared<MeshProperty>(); root->addChild(mesh); } mesh->setMaterialID(index); mesh->setVertexArray(points); mesh->setNormalArray(normals); mesh->setTexcoordArray(texcoords); mesh->setWeightArray(weights); mesh->setFaceArray(faces); last = mesh; } if (_pmd.BoneCount > 0) { Bones bones; InverseKinematics iks; for (auto& it : _pmd.BoneList) { Bone bone; char inbuf[MAX_PATH + 1] = { 0 }; char outbuf[MAX_PATH + 1] = { 0 }; char *in = inbuf; char *out = outbuf; std::size_t in_size = (size_t)MAX_PATH; std::size_t out_size = (size_t)MAX_PATH; memcpy(in, it.Name.Name, sizeof(it.Name.Name)); iconv_t ic = iconv_open("GBK", "SJIS"); iconv(ic, &in, &in_size, &out, &out_size); iconv_close(ic); bone.setName(std::string(outbuf)); bone.setPosition(it.Position); bone.setParent(it.Parent); bone.setChild(it.Child); bones.push_back(bone); } for (auto& it : _pmd.IkList) { IKAttr attr; attr.IKBoneIndex = it.IK; attr.IKTargetBoneIndex = it.Target; attr.IKLimitedRadian = it.LimitOnce; attr.IKLinkCount = it.LinkCount; attr.IKLoopCount = it.LoopCount; for (auto& bone : it.LinkList) { IKChild child; child.BoneIndex = bone; child.MinimumRadian = Vector3::Zero; child.MaximumRadian = Vector3(3.14, 3.14, 3.14); child.RotateLimited = 1; attr.IKList.push_back(child); } iks.push_back(attr); } root->setInverseKinematics(iks); root->setBoneArray(bones); } model.addMesh(root); return true; }
bool SDKMeshHandler::doLoad(Model& model, istream& stream) noexcept { SDKMESH_HEADER hdr; if (!stream.read((char*)&hdr, sizeof(hdr))) return false; std::vector<SDKMESH_VERTEX_BUFFER_HEADER> vbs; std::vector<SDKMESH_INDEX_BUFFER_HEADER> ibs; std::vector<SDKMESH_MESH> meshes; std::vector<SDKMESH_MATERIAL> materials; vbs.resize(hdr.NumVertexBuffers); ibs.resize(hdr.NumIndexBuffers); meshes.resize(hdr.NumMeshes); materials.resize(hdr.NumMaterials); if (!stream.seekg(hdr.VertexStreamHeadersOffset, ios_base::beg)) return false; if (!stream.read((char*)vbs.data(), sizeof(SDKMESH_VERTEX_BUFFER_HEADER) * hdr.NumVertexBuffers)) return false; if (!stream.seekg(hdr.IndexStreamHeadersOffset, ios_base::beg)) return false; if (!stream.read((char*)ibs.data(), sizeof(SDKMESH_INDEX_BUFFER_HEADER) * hdr.NumIndexBuffers)) return false; if (!stream.seekg(hdr.MeshDataOffset, ios_base::beg)) return false; if (!stream.read((char*)meshes.data(), sizeof(SDKMESH_MESH) * hdr.NumMeshes)) return false; if (!stream.seekg(hdr.MaterialDataOffset, ios_base::beg)) return false; if (!stream.read((char*)materials.data(), sizeof(SDKMESH_MATERIAL) * hdr.NumMaterials)) return false; Vector3Array vertices; Vector3Array normals; Vector3Array tangets; Vector2Array texcoord; UintArray faces; MeshPropertyPtr root = nullptr; for (auto& it : materials) { auto material = std::make_shared<MaterialProperty>(); material->set(MATKEY_NAME, it.Name); material->set(MATKEY_COLOR_DIFFUSE, it.Diffuse); material->set(MATKEY_COLOR_AMBIENT, it.Ambient); material->set(MATKEY_COLOR_SPECULAR, Vector3(0.5,0.5,0.5)); material->set(MATKEY_SHININESS, it.Power); if (it.DiffuseTexture[0] != 0) { material->set(MATKEY_TEXTURE_DIFFUSE(0), it.DiffuseTexture); material->set(MATKEY_TEXTURE_AMBIENT(0), it.DiffuseTexture); } if (it.NormalTexture[0] != 0) { material->set(MATKEY_TEXTURE_NORMALS(0), it.NormalTexture); } if (it.SpecularTexture[0] != 0) { material->set(MATKEY_TEXTURE_SPECULAR(0), it.SpecularTexture); } model.addMaterial(material); } for (std::size_t meshIndex = 0; meshIndex < hdr.NumMeshes; meshIndex++) { auto& mesh = meshes[meshIndex]; for (std::size_t i = 0; i < mesh.NumVertexBuffers; i++) { stream.seekg(vbs[i].DataOffset, ios_base::beg); for (std::size_t j = 0; j < vbs[i].NumVertices; j++) { std::uint8_t offset = 0; std::uint8_t buffer[MAX_VERTEX_BUFFER]; stream.read((char*)buffer, vbs[i].StrideBytes); for (std::size_t element = 0; element < MAX_VERTEX_ELEMENTS; element++) { if (vbs[i].Decl[element].Stream != 0) { offset = 0; break; } if (vbs[i].Decl[element].Usage == USAGE_POSITION) { vertices.push_back(*(Vector3*)((char*)&buffer + offset)); offset += sizeof(Vector3); } else if (vbs[i].Decl[element].Usage == USAGE_NORMAL) { normals.push_back(*(Vector3*)((char*)&buffer + offset)); offset += sizeof(Vector3); } else if (vbs[i].Decl[element].Usage == USAGE_TANGENT) { tangets.push_back(*(Vector3*)((char*)&buffer + offset)); offset += sizeof(Vector3); } else if (vbs[i].Decl[element].Usage == USAGE_TEXCOORD) { texcoord.push_back(*(Vector2*)((char*)&buffer + offset)); offset += sizeof(Vector2); } } } } stream.seekg(ibs[mesh.IndexBuffer].DataOffset, ios_base::beg); auto sizeofdata = ibs[mesh.IndexBuffer].SizeBytes / ibs[mesh.IndexBuffer].NumIndices; for (std::size_t j = 0; j < ibs[mesh.IndexBuffer].NumIndices; j++) { std::uint32_t buffer = 0; stream.read((char*)&buffer, sizeofdata); faces.push_back(buffer); } MeshPropertyPtr subset = std::make_shared<MeshProperty>(); subset->setMaterialID(0); subset->setVertexArray(vertices); subset->setNormalArray(normals); subset->setTexcoordArray(texcoord); subset->setTangentArray(tangets); subset->setFaceArray(faces); if (root) root->addChild(subset); else root = subset; } model.addMesh(root); return true; }