CSceneNode* CSkpMeshImporterImpler::LoadModel(SUModelRef model) { // Get the entities container of the model. SUEntitiesRef entities = SU_INVALID; SUResult res = SUModelGetEntities(model, &entities); //size_t faceCount = 0; //res = SUEntitiesGetNumFaces(entities, &faceCount); //vector faces; //size_t count; //res = SUEntitiesGetFaces(entities, faceCount, &faces[0], &faceCount); assert(res == SU_ERROR_NONE); // Load materials LoadMaterials(model); // Create a texture writer SUSetInvalid(m_textureWriter); res = SUTextureWriterCreate(&m_textureWriter); assert(res == SU_ERROR_NONE); // Entities recursive CSceneNode* pGroup = new CGroupNode(); SUMaterialRef eleMaterial = SU_INVALID; LoadEntitiesRecursive(entities, eleMaterial, pGroup); SUAxesRef axis; SUModelGetAxes(model,&axis); SUTransformation transform; SUAxesGetTransform(axis,&transform); CMatrix4d mat = CMatrix4d::Identity; memcpy(mat.Ptr(), transform.values, sizeof(double) * 16); pGroup->SetTransform(mat.Inverse().Matrix4f()); return pGroup; } void CSkpMeshImporterImpler::LoadEntitiesRecursive(SUEntitiesRef entities, SUMaterialRef parMaterial, CSceneNode* pParent) { // Load component instances size_t instanceCount = 0; SUResult res = SUEntitiesGetNumInstances(entities, &instanceCount); assert(res == SU_ERROR_NONE); if (instanceCount > 0) { std::vector instances(instanceCount); res = SUEntitiesGetInstances(entities, instanceCount, &instances[0], &instanceCount); assert(res == SU_ERROR_NONE); for (size_t i=0; i 0) { std::vector groups(groupCount); SUEntitiesGetGroups(entities, groupCount, &groups[0], &groupCount); assert(res == SU_ERROR_NONE); for (size_t i=0; i0) { CGroupNode* pTempParent = dynamic_cast(pParent); if (pTempParent) { CVisualNode* pNode = new CVisualNode(); LoadFaces(entities, pNode, parMaterial); pTempParent->AddChild(pNode); } } } SUEntitiesRef CSkpMeshImporterImpler::LoadComponentInstance(SUComponentInstanceRef instance, SUMaterialRef eleMaterial, CSceneNode* pParent, CSceneNode* &pGGPNode) { // Convert to entities SUComponentDefinitionRef component_definition; SUResult res = SUComponentInstanceGetDefinition(instance, &component_definition); assert(res == SU_ERROR_NONE); SUEntitiesRef entities; res = SUComponentDefinitionGetEntities(component_definition, &entities); assert(res == SU_ERROR_NONE); // Load transform SUTransformation transform; res = SUComponentInstanceGetTransform(instance, &transform); assert(res == SU_ERROR_NONE); CMatrix4d mat = CMatrix4d::Identity; memcpy(mat.Ptr(), transform.values, sizeof(double) * 16); mat[3][0] *= m_fUnitFactor; mat[3][1] *= m_fUnitFactor; mat[3][2] *= m_fUnitFactor; std::vector skpEntityNodes = CreateGGPNodeBySkpEntities(entities, eleMaterial, pParent); pGGPNode = skpEntityNodes.at(0); for(unsigned int i = 0; i < skpEntityNodes.size(); i++) { assert(skpEntityNodes[i] != nullptr); if (skpEntityNodes[i] != nullptr) { skpEntityNodes[i]->SetTransform(mat.Matrix4f()); } } return entities; } SUEntitiesRef CSkpMeshImporterImpler::LoadGroup(SUGroupRef group, SUMaterialRef eleMaterial, CSceneNode* pParent, CSceneNode* &pGGPNode) { // Convert to entities SUComponentDefinitionRef component_definition; SUResult res = SUGroupGetDefinition(group, &component_definition); assert(res == SU_ERROR_NONE); SUEntitiesRef entities; res = SUComponentDefinitionGetEntities(component_definition, &entities); assert(res == SU_ERROR_NONE); // Load transform SUTransformation transform; res = SUGroupGetTransform(group, &transform); assert(res == SU_ERROR_NONE); CMatrix4d mat = CMatrix4d::Identity; memcpy(mat.Ptr(), transform.values, sizeof(double) * 16); mat[3][0] *= m_fUnitFactor; mat[3][1] *= m_fUnitFactor; mat[3][2] *= m_fUnitFactor; std::vector skpEntityNodes = CreateGGPNodeBySkpEntities(entities, eleMaterial, pParent); pGGPNode = skpEntityNodes.at(0); for(unsigned int i = 0; i < skpEntityNodes.size(); i++) { assert(skpEntityNodes[i] != nullptr); if (skpEntityNodes[i] != nullptr) { skpEntityNodes[i]->SetTransform(mat.Matrix4f()); } } return entities; } std::vector CSkpMeshImporterImpler::CreateGGPNodeBySkpEntities(SUEntitiesRef entities, SUMaterialRef parMaterial, CSceneNode* pParent) { std::vector skpEntitiyNodes; // Parameter check if (SUIsInvalid(entities) || pParent == nullptr) { assert(false); return skpEntitiyNodes; } CGroupNode* pTempParent = dynamic_cast(pParent); assert(pTempParent != nullptr); // Child and mesh info size_t instanceCount = 0; SUResult res = SUEntitiesGetNumInstances(entities, &instanceCount); assert(res == SU_ERROR_NONE); size_t groupCount = 0; res = SUEntitiesGetNumGroups(entities, &groupCount); assert(res == SU_ERROR_NONE); size_t faceCount = 0; res = SUEntitiesGetNumFaces(entities, &faceCount); assert(res == SU_ERROR_NONE); // Have no child, only mesh if(instanceCount == 0 && groupCount == 0) { CVisualNode* pNode = new CVisualNode(); pTempParent->AddChild(pNode); LoadFaces(entities, pNode, parMaterial); skpEntitiyNodes.push_back(pNode); if (m_bImportEdges) { CSkpLineNode* pSkpNode = new CSkpLineNode(); pTempParent->AddChild(pSkpNode); LoadEdges(entities, pSkpNode, CColor::Black); skpEntitiyNodes.push_back(pSkpNode); pSkpNode->SetVisible(false); } return skpEntitiyNodes; } else { // Have both child and mesh if (faceCount > 0) { CGroupNode* pMiddleNode = new CGroupNode(); pTempParent->AddChild(pMiddleNode); CVisualNode* pNode = new CVisualNode(); pMiddleNode->AddChild(pNode); LoadFaces(entities, pNode, parMaterial); if (m_bImportEdges) { CSkpLineNode* pSkpNode = new CSkpLineNode(); pMiddleNode->AddChild(pSkpNode); LoadEdges(entities, pSkpNode, CColor::Black); pSkpNode->SetVisible(false); } skpEntitiyNodes.push_back(pMiddleNode); return skpEntitiyNodes; } // Have child, no mesh else { CGroupNode* pNode = new CGroupNode(); pTempParent->AddChild(pNode); skpEntitiyNodes.push_back(pNode); return skpEntitiyNodes; } } } void CSkpMeshImporterImpler::LoadFaces(SUEntitiesRef entities, CVisualNode* pGGPNode, SUMaterialRef parMaterial) { // Parameter check if (SUIsInvalid(entities) || (pGGPNode == nullptr)) { assert(false); return; } size_t faceCount = 0; SUResult res = SUEntitiesGetNumFaces(entities, &faceCount); assert(res == SU_ERROR_NONE); if (faceCount > 0) { std::vector faces(faceCount); res = SUEntitiesGetFaces(entities, faceCount, &faces[0], &faceCount); assert(res == SU_ERROR_NONE); SUBoundingBox3D box; res = SUEntitiesGetBoundingBox(entities, &box); assert(res == SU_ERROR_NONE); // Divide faces by material std::map , std::vector> materialFaces; std::vector is_affineFaces(faceCount); std::vector idTextureFaces(faceCount); std::vector textureScaleU(faceCount); std::vector textureScaleV(faceCount); for (size_t i=0; isecond, is_affineFaces[index]); CStateSet* pStateSetFront = GetStateSetByID(it->first.first); CStateSet* pStateSetBack = GetStateSetByID(it->first.second); if (pStateSetBack != nullptr) { ////pStateSetFront->AddTextureState(pStateSetBack->GetTextureState(0)); //if (pStateSetFront->GetShaderProgram() != nullptr) //{ // pStateSetFront->GetShaderProgram()->GetFragmentShader()->LoadShaderFromFile(L"D:/shader_fs.glsl"); // CShaderUniform* pShaderUniform = 0; // pShaderUniform = new CShaderUniform("isDoubleFace", true); // pStateSetFront->AddUniform(CShader::ST_FRAGMENT_SHADER, pShaderUniform); // //pStateSetFront->AddTextureState(pStateSetBack->GetTextureState(0)); // pStateSetFront->RemoveAllTextureStates(); // pStateSetFront->CreateTextureState(L"D:/a.jpg", 1); //} } renderable->SetStateSet(pStateSetFront); pGGPNode->AddRenderable(renderable); index++; } } } void CSkpMeshImporterImpler::LoadEdges(SUEntitiesRef entities, CSkpLineNode* pGGPNode, CColor color) { // Parameter check if (SUIsInvalid(entities) || (pGGPNode == nullptr)) { assert(false); return; } std::vector sktEdges; size_t edgeCount = 0; SUEntitiesGetNumEdges(entities, false, &edgeCount); if (edgeCount>0) { sktEdges.resize(edgeCount); SUEntitiesGetEdges(entities, false, edgeCount, &sktEdges[0], &edgeCount); } // Create renderable CPrimitiveRenderable* pRenderable = new CPrimitiveRenderable; // Declaration pRenderable->SetPrimitiveType(PT_LINES); Vec3List positionArr; UIntList indexArr; int j = 0; for(unsigned int i=0; i(j++)); indexArr.push_back(static_cast(j++)); } if(positionArr.size() > 1) { pRenderable->SetVertexArray(positionArr); pRenderable->SetIndexArray(indexArr); pRenderable->GetOrCreateStateSet()->SetMaterial(color); pGGPNode->AddRenderable(pRenderable); } } CRenderable* CSkpMeshImporterImpler::LoadMesh(const std::vector& faces, bool isAffine) { Vec3List positionArr; Vec3List normalArr; ColorList colorArr; Vec2List texCoordArr; UIntList indexArr; size_t iBaseIndex = 0; for (size_t i=0; i Indices(indicesCount); res = SUMeshHelperGetVertexIndices(mesh, indicesCount, &Indices[0], &retrievedCount); assert(res == SU_ERROR_NONE); for (size_t j = 0; j < indicesCount; ++j) { indexArr.push_back(static_cast(Indices[j] + iBaseIndex)); } // Get number of vertices. size_t vertexCount; res = SUMeshHelperGetNumVertices(mesh, &vertexCount); assert(res == SU_ERROR_NONE); iBaseIndex += vertexCount; // Get vertices. std::vector vertices(vertexCount); res = SUMeshHelperGetVertices(mesh, vertexCount, &vertices[0], &vertexCount); assert(res == SU_ERROR_NONE); for (size_t j = 0; j < vertexCount; ++j) { CVector3d position(vertices[j].x, vertices[j].y, vertices[j].z); position *= m_fUnitFactor; positionArr.push_back(position.Vec3f()); } // Get Normals std::vector normals(vertexCount); res = SUMeshHelperGetNormals(mesh, vertexCount, &normals[0], &vertexCount); assert(res == SU_ERROR_NONE); for (size_t j = 0; j < vertexCount; ++j) { CVector3d normal(normals[j].x, normals[j].y, normals[j].z); normalArr.push_back(normal.Vec3f()); } // Front Texture Coordinates std::vector textureCoords(vertexCount); res = SUTextureWriterGetFrontFaceUVCoords(m_textureWriter, faces[i], vertexCount, &vertices[0], &textureCoords[0]); assert(res == SU_ERROR_NONE); for (size_t j = 0; j < vertexCount; ++j) { CVector2d texCoord(textureCoords[j].x, textureCoords[j].y);; texCoordArr.push_back(texCoord.Vec2f()); } res = SUMeshHelperRelease(&mesh); assert(res == SU_ERROR_NONE); } else { SUMeshHelperRef polyMesh = SU_INVALID; SUMeshHelperCreate(&polyMesh, faces[i]); size_t result; size_t nVertices = 0; size_t nIndices = 0; if (SUIsValid(polyMesh)) { SUMeshHelperGetNumVertices(polyMesh, &nVertices); std::vector points(nVertices); std::vector uvs(nVertices); std::vector normals(nVertices); SUMeshHelperGetVertices(polyMesh, nVertices, &points[0], &result); SUMeshHelperGetNormals(polyMesh, nVertices, &normals[0], &result); SUMeshHelperGetFrontSTQCoords(polyMesh, nVertices, &uvs[0], &result); SUMeshHelperGetNumTriangles(polyMesh, &nIndices); nIndices = nIndices * 3; std::vector indices(nIndices); SUMeshHelperGetVertexIndices(polyMesh, nIndices, &indices[0], &result); // Release polyMesh SUMeshHelperRelease(&polyMesh); for (size_t j = 0; j < nIndices; ++j) { CVector3d position(points[indices[j]].x, points[indices[j]].y, points[indices[j]].z); positionArr.push_back(position.Vec3f()); CVector3d normal(normals[indices[j]].x, normals[indices[j]].y, normals[indices[j]].z); normalArr.push_back(normal.Vec3f()); CVector2d texCoord(uvs[indices[j]].x / uvs[indices[j]].z, uvs[indices[j]].y / uvs[indices[j]].z); texCoordArr.push_back(texCoord.Vec2f()); } } //SUUVHelperRef uv_helper; //res = SUFaceGetUVHelperWithTextureHandle(faces[i], true, false, m_textureWriter, id, &uv_helper); //assert(res == SU_ERROR_NONE); //if (res == SU_ERROR_NONE) //{ // for (int iv = 0; iv < vertices.size(); iv++) // { // SUUVQ uvq; // res = SUUVHelperGetFrontUVQ(uv_helper, &vertices[iv], &uvq); // if (res == SU_ERROR_NONE) // { // double u; // double v; // if (scaleU != 0) // { // u = 1.0; // //u = scaleU; // } // if (scaleV != 0) // { // v = 1.0; // //v = scaleV; // } // texCoordArr.push_back(CVector2d(uvq.u / (uvq.q * u), uvq.v / (uvq.q * v)).Vec2f()); // } // } //} //SUUVHelperRelease(&uv_helper); } } colorArr.assign(positionArr.size(), CColor::Gray); return SkpImporterHelper::CreateRenderable(positionArr, normalArr, colorArr, texCoordArr, indexArr); } void CSkpMeshImporterImpler::LoadMaterials(SUModelRef model) { // Get the materials of model size_t materialCount = 0; SUResult res = SUModelGetNumMaterials(model, &materialCount); assert(res == SU_ERROR_NONE); // Parse material if (materialCount>0) { std::vector materials(materialCount); res = SUModelGetMaterials(model, materialCount, &materials[0], &materialCount); assert(res == SU_ERROR_NONE); for (size_t i=0; i(alpha); diffuse.SetByFloatArray(arrayDiffse); // Texture type std::string strTexName; if(type == SUMaterialType_Textured || type == SUMaterialType_ColorizedTexture) { SUTextureRef texture = SU_INVALID; res = SUMaterialGetTexture(skpMaterial, &texture); switch (res) { case SU_ERROR_NONE: { SUStringRef fileName = SU_INVALID; SUStringCreate(&fileName); SUTextureGetFileName(texture, &fileName); if(SUIsValid(fileName)) { strTexName = SkpImporterHelper::SUString2String(fileName); } SUStringRelease(&fileName); // Write texture to resource path if (SUIsValid(texture)) { std::string strFullPath = m_strResourcesPath + strTexName; bool bExist = boost::filesystem::exists(GStdStringTrans::Utf8ToAnsi(strFullPath.c_str())); if (!bExist) { res = SUTextureWriteToFile(texture, strFullPath.c_str()); assert(res == SU_ERROR_NONE); } } break; } case SU_ERROR_NO_DATA: { std::cout <<"No Texture \n"; break; } default : break; } } // Create CStateSet CStateSet* pStateSet = nullptr; if (m_pMaterialLibrary) { CAppearanceInstancePtr pInstance = m_pMaterialLibrary->CreateMaterial("Generic"); CVector4f color; CColor::MakeFloatArray(diffuse, &color[0]); pInstance->SetDiffuse(color); pInstance->SetAmbient(color); pInstance->SetSpecular(CVector4f(0.0f, 0.0f, 0.0f, 1.0f)); pInstance->SetShininess(0.0f); pInstance->SetTransparent(static_cast(alpha)); pInstance->SetName(GStdStringTrans::Utf8ToAnsi(strMatName.c_str())); pInstance->SetEditType(2);//¿É±à¼­²»¿Éɾ³ý // Texture if(strTexName != "") { std::string strFile = m_strResourcesPath + strTexName; wchar_t* pChar = GStdStringTrans::Utf8ToUnicode(strFile.c_str()); pInstance->SetUseDiffuseTexture(true); CAppearanceInstancePtr pDiffuseTexture = pInstance->GetDiffuseTexture(); pDiffuseTexture->SetTextureFile(GStdStringTrans::WstringToString(pChar)); delete [] pChar; pInstance->SetDiffuse(CVector4f(1.0f, 1.0f, 1.0f, color.W)); pInstance->SetAmbient(CVector4f(1.0f, 1.0f, 1.0f, color.W)); } WString id = GStdStringTrans::StringToWString(pInstance->GetId()); m_pMaterialLibrary->UpdateMaterial(id); pStateSet = m_pMaterialLibrary->GetStateSetbyID(id).get(); pStateSet->SetFaceMode(FM_FRONT_AND_BACK); } else { pStateSet = new CStateSet(); pStateSet->SetDiffuse(diffuse); pStateSet->SetAmbient(diffuse); pStateSet->SetSpecular(CColor::Black); pStateSet->SetEmissive(CColor::Black); if(strTexName != "") { std::string strFullPath = m_strResourcesPath.c_str() + strTexName; wchar_t* pChar = GStdStringTrans::Utf8ToUnicode(strFullPath.c_str()); pStateSet->CreateTextureState(pChar); delete [] pChar; pStateSet->SetDiffuse(CColor(255, 255, 255, diffuse.A)); pStateSet->SetAmbient(CColor(255, 255, 255, diffuse.A)); } if ((alpha < 1.0)) { pStateSet->SetSceneBlending(SBT_TRANSPARENT_ALPHA); pStateSet->SetAlphaTestReferenceValue(0.0f); pStateSet->SetAlphaTestFunction(FTF_GREATER); } pStateSet->SetFaceMode(FM_FRONT_AND_BACK); //pStateSet->SetLightModelTwoSided(true); } m_mapIdSkpMaterials[id] = skpMaterial; m_mapIdGGPmaterials[id] = pStateSet; return pStateSet; } std::wstring CSkpMeshImporterImpler::GetMaterialId(SUMaterialRef sktMaterial) { for (auto it=m_mapIdSkpMaterials.begin(); it != m_mapIdSkpMaterials.end(); ++it) { if (SUAreEqual(sktMaterial, it->second)) { return it->first; } } return L""; } CStateSet* CSkpMeshImporterImpler::GetStateSetByID(const std::wstring& materilId) { auto it = m_mapIdGGPmaterials.find(materilId); if (it != m_mapIdGGPmaterials.end()) { return it->second.get(); } return nullptr; }