char *find_material(struct aiMaterial *material) { struct aiString str; char shader[500], *p; char *name; int i; for (i = 0; i < nummats; i++) if (matlist[i].material == material) return matlist[i].shader; aiGetMaterialString(material, AI_MATKEY_NAME, &str); name = str.data; strcpy(shader, clean_material_name(name)); strcat(shader, "+"); if (!aiGetMaterialString(material, AI_MATKEY_TEXTURE_DIFFUSE(0), &str)) strcat(shader, get_base_name(str.data)); else strcat(shader, "unknown"); p = strrchr(shader, '.'); if (p) *p = 0; p = shader; while (*p) { *p = tolower(*p); p++; } matlist[nummats].name = name; matlist[nummats].material = material; matlist[nummats].shader = strdup(shader); return matlist[nummats++].shader; }
void process_material(struct goat3d_material *mtl, struct aiMaterial *aimtl) { struct aiString aistr; struct aiColor4D color; float val; if(aiGetMaterialString(aimtl, AI_MATKEY_NAME, &aistr) == aiReturn_SUCCESS) { goat3d_set_mtl_name(mtl, aistr.data); } if(aiGetMaterialColor(aimtl, AI_MATKEY_COLOR_DIFFUSE, &color) == aiReturn_SUCCESS) { goat3d_set_mtl_attrib3f(mtl, GOAT3D_MAT_ATTR_DIFFUSE, color.r, color.g, color.b); } if(aiGetMaterialColor(aimtl, AI_MATKEY_COLOR_SPECULAR, &color) == aiReturn_SUCCESS) { float sstr = 1.0; aiGetMaterialFloatArray(aimtl, AI_MATKEY_SHININESS_STRENGTH, &sstr, 0); goat3d_set_mtl_attrib3f(mtl, GOAT3D_MAT_ATTR_SPECULAR, color.r * sstr, color.g * sstr, color.b * sstr); } if(aiGetMaterialFloatArray(aimtl, AI_MATKEY_BUMPSCALING, &val, 0) == aiReturn_SUCCESS) { goat3d_set_mtl_attrib3f(mtl, GOAT3D_MAT_ATTR_BUMP, val, val, val); } if(aiGetMaterialFloatArray(aimtl, AI_MATKEY_REFLECTIVITY, &val, 0) == aiReturn_SUCCESS) { goat3d_set_mtl_attrib1f(mtl, GOAT3D_MAT_ATTR_REFLECTION, val); } if(aiGetMaterialFloatArray(aimtl, AI_MATKEY_OPACITY, &val, 0) == aiReturn_SUCCESS) { goat3d_set_mtl_attrib1f(mtl, GOAT3D_MAT_ATTR_TRANSMISSION, 1.0 - val); } if(aiGetMaterialString(aimtl, AI_MATKEY_TEXTURE_DIFFUSE(0), &aistr) == aiReturn_SUCCESS) { goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_DIFFUSE, aistr.data); } if(aiGetMaterialString(aimtl, AI_MATKEY_TEXTURE_SPECULAR(0), &aistr) == aiReturn_SUCCESS) { goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_SPECULAR, aistr.data); } if(aiGetMaterialString(aimtl, AI_MATKEY_TEXTURE_SHININESS(0), &aistr) == aiReturn_SUCCESS) { goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_SHININESS, aistr.data); } if(aiGetMaterialString(aimtl, AI_MATKEY_TEXTURE_NORMALS(0), &aistr) == aiReturn_SUCCESS) { goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_NORMAL, aistr.data); } if(aiGetMaterialString(aimtl, AI_MATKEY_TEXTURE_REFLECTION(0), &aistr) == aiReturn_SUCCESS) { goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_REFLECTION, aistr.data); } if(aiGetMaterialString(aimtl, AI_MATKEY_TEXTURE_OPACITY(0), &aistr) == aiReturn_SUCCESS) { /* TODO this is semantically inverted... maybe add an alpha attribute? */ goat3d_set_mtl_attrib_map(mtl, GOAT3D_MAT_ATTR_TRANSMISSION, aistr.data); } }
//------------------------------------------------------------------------------- int CMaterialManager::CreateMaterial( AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource) { #if 1//??? ai_assert(0 != pcMesh); ai_assert(0 != pcSource); // ID3DXFROMWINEBuffer* piBuffer; // extract all properties from the ASSIMP material structure const aiMaterial* pcMat = mr->GetAsset()->pcScene->mMaterials[pcSource->mMaterialIndex]; // // DIFFUSE COLOR -------------------------------------------------- // if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_DIFFUSE, (aiColor4D*)&pcMesh->vDiffuseColor)) { pcMesh->vDiffuseColor.x = 1.0f; pcMesh->vDiffuseColor.y = 1.0f; pcMesh->vDiffuseColor.z = 1.0f; pcMesh->vDiffuseColor.w = 1.0f; } // // SPECULAR COLOR -------------------------------------------------- // if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_SPECULAR, (aiColor4D*)&pcMesh->vSpecularColor)) { pcMesh->vSpecularColor.x = 1.0f; pcMesh->vSpecularColor.y = 1.0f; pcMesh->vSpecularColor.z = 1.0f; pcMesh->vSpecularColor.w = 1.0f; } // // AMBIENT COLOR -------------------------------------------------- // if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_AMBIENT, (aiColor4D*)&pcMesh->vAmbientColor)) { pcMesh->vAmbientColor.x = 0.0f; pcMesh->vAmbientColor.y = 0.0f; pcMesh->vAmbientColor.z = 0.0f; pcMesh->vAmbientColor.w = 1.0f; } // // EMISSIVE COLOR ------------------------------------------------- // if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_EMISSIVE, (aiColor4D*)&pcMesh->vEmissiveColor)) { pcMesh->vEmissiveColor.x = 0.0f; pcMesh->vEmissiveColor.y = 0.0f; pcMesh->vEmissiveColor.z = 0.0f; pcMesh->vEmissiveColor.w = 1.0f; } // // Opacity -------------------------------------------------------- // if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_OPACITY,&pcMesh->fOpacity)) { pcMesh->fOpacity = 1.0f; } // // Shading Model -------------------------------------------------- // bool bDefault = false; if(AI_SUCCESS != aiGetMaterialInteger(pcMat,AI_MATKEY_SHADING_MODEL,(int*)&pcMesh->eShadingMode )) { bDefault = true; pcMesh->eShadingMode = aiShadingMode_Gouraud; } // // Shininess ------------------------------------------------------ // if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_SHININESS,&pcMesh->fShininess)) { // assume 15 as default shininess pcMesh->fShininess = 15.0f; } else if (bDefault)pcMesh->eShadingMode = aiShadingMode_Phong; // // Shininess strength ------------------------------------------------------ // if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_SHININESS_STRENGTH,&pcMesh->fSpecularStrength)) { // assume 1.0 as default shininess strength pcMesh->fSpecularStrength = 1.0f; } aiString szPath; aiTextureMapMode mapU(aiTextureMapMode_Wrap),mapV(aiTextureMapMode_Wrap); bool bib =false; if (pcSource->mTextureCoords[0]) { // // DIFFUSE TEXTURE ------------------------------------------------ // if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_DIFFUSE(0),&szPath)) { LoadTexture(&pcMesh->piDiffuseTexture,&szPath); aiGetMaterialInteger(pcMat,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0),(int*)&mapU); aiGetMaterialInteger(pcMat,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0),(int*)&mapV); } // // SPECULAR TEXTURE ------------------------------------------------ // if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SPECULAR(0),&szPath)) { LoadTexture(&pcMesh->piSpecularTexture,&szPath); } // // OPACITY TEXTURE ------------------------------------------------ // if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_OPACITY(0),&szPath)) { LoadTexture(&pcMesh->piOpacityTexture,&szPath); } else { int flags = aiTextureFlags_IgnoreAlpha;//???0; aiGetMaterialInteger(pcMat,AI_MATKEY_TEXFLAGS_DIFFUSE(0),&flags); // try to find out whether the diffuse texture has any // non-opaque pixels. If we find a few, use it as opacity texture if ((pcMesh->piDiffuseTexture!=-1) && !(flags & aiTextureFlags_IgnoreAlpha) && HasAlphaPixels(pcMesh->piDiffuseTexture)) { int iVal; // NOTE: This special value is set by the tree view if the user // manually removes the alpha texture from the view ... if (AI_SUCCESS != aiGetMaterialInteger(pcMat,"no_a_from_d",0,0,&iVal)) { pcMesh->piOpacityTexture = pcMesh->piDiffuseTexture; // pcMesh->piOpacityTexture->AddRef(); } } } // // AMBIENT TEXTURE ------------------------------------------------ // if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_AMBIENT(0),&szPath)) { LoadTexture(&pcMesh->piAmbientTexture,&szPath); } // // EMISSIVE TEXTURE ------------------------------------------------ // if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_EMISSIVE(0),&szPath)) { LoadTexture(&pcMesh->piEmissiveTexture,&szPath); } // // Shininess TEXTURE ------------------------------------------------ // if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SHININESS(0),&szPath)) { LoadTexture(&pcMesh->piShininessTexture,&szPath); } // // Lightmap TEXTURE ------------------------------------------------ // if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_LIGHTMAP(0),&szPath)) { LoadTexture(&pcMesh->piLightmapTexture,&szPath); } // // NORMAL/HEIGHT MAP ------------------------------------------------ // bool bHM = false; if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_NORMALS(0),&szPath)) { LoadTexture(&pcMesh->piNormalTexture,&szPath); } else { if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_HEIGHT(0),&szPath)) { LoadTexture(&pcMesh->piNormalTexture,&szPath); } else bib = true; bHM = true; } // normal/height maps are sometimes mixed up. Try to detect the type // of the texture automatically if (pcMesh->piNormalTexture!=-1) { HMtoNMIfNecessary(pcMesh->piNormalTexture, &pcMesh->piNormalTexture,bHM); } } // check whether a global background texture is contained // in this material. Some loaders set this value ... if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_GLOBAL_BACKGROUND_IMAGE,&szPath)) { // CBackgroundPainter::Instance().SetTextureBG(szPath.data); } // BUGFIX: If the shininess is 0.0f disable phong lighting // This is a workaround for some meshes in the DX SDK (e.g. tiny.x) // FIX: Added this check to the x-loader, but the line remains to // catch other loader doing the same ... if (0.0f == pcMesh->fShininess){ pcMesh->eShadingMode = aiShadingMode_Gouraud; } int two_sided = 0; aiGetMaterialInteger(pcMat,AI_MATKEY_TWOSIDED,&two_sided); pcMesh->twosided = (two_sided != 0); // check whether we have already a material using the same // shader. This will decrease loading time rapidly ... for (unsigned int i = 0; i < mr->GetAsset()->pcScene->mNumMeshes;++i) { if (mr->GetAsset()->pcScene->mMeshes[i] == pcSource) { break; } AssetHelper::MeshHelper* pc = mr->GetAsset()->apcMeshes[i]; if ((pcMesh->piDiffuseTexture !=-1 ? true : false) != (pc->piDiffuseTexture !=-1 ? true : false)) continue; if ((pcMesh->piSpecularTexture !=-1 ? true : false) != (pc->piSpecularTexture !=-1 ? true : false)) continue; if ((pcMesh->piAmbientTexture !=-1 ? true : false) != (pc->piAmbientTexture !=-1 ? true : false)) continue; if ((pcMesh->piEmissiveTexture !=-1 ? true : false) != (pc->piEmissiveTexture !=-1 ? true : false)) continue; if ((pcMesh->piNormalTexture !=-1 ? true : false) != (pc->piNormalTexture !=-1 ? true : false)) continue; if ((pcMesh->piOpacityTexture !=-1 ? true : false) != (pc->piOpacityTexture !=-1 ? true : false)) continue; if ((pcMesh->piShininessTexture !=-1 ? true : false) != (pc->piShininessTexture !=-1 ? true : false)) continue; if ((pcMesh->piLightmapTexture !=-1 ? true : false) != (pc->piLightmapTexture !=-1 ? true : false)) continue; if ((pcMesh->eShadingMode != aiShadingMode_Gouraud ? true : false) != (pc->eShadingMode != aiShadingMode_Gouraud ? true : false)) continue; if ((pcMesh->fOpacity != 1.0f ? true : false) != (pc->fOpacity != 1.0f ? true : false)) continue; if (pcSource->HasBones() != mr->GetAsset()->pcScene->mMeshes[i]->HasBones()) continue; // we can reuse this material if (pc->piEffect!=-1) { pcMesh->piEffect = pc->piEffect; pc->bSharedFX = pcMesh->bSharedFX = true; // pcMesh->piEffect->AddRef(); return 2; } } m_iShaderCount++; //if(mr->m_piDefaultEffect==-1) if(0) { typedef struct _D3DXFROMWINEMACRO { LPCSTR Name; LPCSTR Definition; } D3DXFROMWINEMACRO, *LPD3DXFROMWINEMACRO; D3DXFROMWINEMACRO sMacro[64]; // build macros for the HLSL compiler unsigned int iCurrent = 0; if (pcMesh->piDiffuseTexture!=-1) { sMacro[iCurrent].Name = "AV_DIFFUSE_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; if (mapU == aiTextureMapMode_Wrap) sMacro[iCurrent].Name = "AV_WRAPU"; else if (mapU == aiTextureMapMode_Mirror) sMacro[iCurrent].Name = "AV_MIRRORU"; else // if (mapU == aiTextureMapMode_Clamp) sMacro[iCurrent].Name = "AV_CLAMPU"; sMacro[iCurrent].Definition = "1"; ++iCurrent; if (mapV == aiTextureMapMode_Wrap) sMacro[iCurrent].Name = "AV_WRAPV"; else if (mapV == aiTextureMapMode_Mirror) sMacro[iCurrent].Name = "AV_MIRRORV"; else // if (mapV == aiTextureMapMode_Clamp) sMacro[iCurrent].Name = "AV_CLAMPV"; sMacro[iCurrent].Definition = "1"; ++iCurrent; } if (pcMesh->piSpecularTexture!=-1) { sMacro[iCurrent].Name = "AV_SPECULAR_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; } if (pcMesh->piAmbientTexture!=-1) { sMacro[iCurrent].Name = "AV_AMBIENT_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; } if (pcMesh->piEmissiveTexture!=-1) { sMacro[iCurrent].Name = "AV_EMISSIVE_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; } char buff[32]; if (pcMesh->piLightmapTexture!=-1) { sMacro[iCurrent].Name = "AV_LIGHTMAP_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; int idx; if(AI_SUCCESS == aiGetMaterialInteger(pcMat,AI_MATKEY_UVWSRC_LIGHTMAP(0),&idx) && idx >= 1 && pcSource->mTextureCoords[idx]) { sMacro[iCurrent].Name = "AV_TWO_UV"; sMacro[iCurrent].Definition = "1"; ++iCurrent; sMacro[iCurrent].Definition = "IN.TexCoord1"; } else sMacro[iCurrent].Definition = "IN.TexCoord0"; sMacro[iCurrent].Name = "AV_LIGHTMAP_TEXTURE_UV_COORD"; ++iCurrent;float f= 1.f; aiGetMaterialFloat(pcMat,AI_MATKEY_TEXBLEND_LIGHTMAP(0),&f); stx_snprintf(buff,32,"%f",f); sMacro[iCurrent].Name = "LM_STRENGTH"; sMacro[iCurrent].Definition = buff; ++iCurrent; } if ((pcMesh->piNormalTexture!=-1) && !bib) { sMacro[iCurrent].Name = "AV_NORMAL_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; } if (pcMesh->piOpacityTexture!=-1) { sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; if (pcMesh->piOpacityTexture == pcMesh->piDiffuseTexture) { sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE_REGISTER_MASK"; sMacro[iCurrent].Definition = "a"; ++iCurrent; } else { sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE_REGISTER_MASK"; sMacro[iCurrent].Definition = "r"; ++iCurrent; } } if (pcMesh->eShadingMode != aiShadingMode_Gouraud && !mr->m_sOptions.bNoSpecular) { sMacro[iCurrent].Name = "AV_SPECULAR_COMPONENT"; sMacro[iCurrent].Definition = "1"; ++iCurrent; if (pcMesh->piShininessTexture!=-1) { sMacro[iCurrent].Name = "AV_SHININESS_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; } } if (1.0f != pcMesh->fOpacity) { sMacro[iCurrent].Name = "AV_OPACITY"; sMacro[iCurrent].Definition = "1"; ++iCurrent; } if( pcSource->HasBones()) { sMacro[iCurrent].Name = "AV_SKINNING"; sMacro[iCurrent].Definition = "0";//???"1"; ++iCurrent; } /* // If a cubemap is active, we'll need to lookup it for calculating // a physically correct reflection if (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode()) { sMacro[iCurrent].Name = "AV_SKYBOX_LOOKUP"; sMacro[iCurrent].Definition = "1"; ++iCurrent; }*/ sMacro[iCurrent].Name = 0; sMacro[iCurrent].Definition = 0; //Construct defines from sMacro and compine with mr->m_szMaterialShader string std::string extra; unsigned int iiCurrent = 0; while ((sMacro[iiCurrent].Name != 0)&& (sMacro[iiCurrent].Definition != 0)) { extra.append("#define "); extra.append(sMacro[iiCurrent].Name); extra.append(" "); extra.append(sMacro[iiCurrent].Definition); extra.append(";\n"); iiCurrent++; } // compile the shader #if 1 const char *ShaderName = mr->m_szShaderName.c_str(); //LOG_PRINT("ShaderName=%s\n", ShaderName); ShaderID shd=MeshRendererShadersFactory::GetShader(ShaderName, "main", "main"); //LOG_PRINT("m_SimpleShader=%s\n", m_SimpleShader); #elif 0 const char *m_SimpleShader = MeshRendererShadersFactory::GetShader("SimpleShader"); mr->m_piDefaultEffect=IRenderer::GetRendererInstance()->addHLSLShader( m_SimpleShader, "main", "main");//D1??? #elif 0 mr->m_piDefaultEffect=IRenderer::GetRendererInstance()->addHLSLShader( g_szMaterialShader.c_str(), "MaterialVShader_D1", "MaterialPShaderSpecular_D1",0,0,extra.c_str());//D1??? #elif 0 mr->m_piDefaultEffect=IRenderer::GetRendererInstance()->addHLSLShader( g_szDefaultShader.c_str(), "DefaultVShader", "DefaultPShaderSpecular_D1",0,0,extra.c_str());//D1??? #endif //mr->m_piMaterialEffect=mr->m_piDefaultEffect; #if 1 FormatDesc Fmt[] = { #if 0 { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, { 0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 }, { 0, 28, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0 }, { 0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 0 }, { 0, 52, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, { 0, 60, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 }, { 0, 68, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES, 0 }, { 0, 72, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0 }, #else {0, TYPE_VERTEX, FORMAT_FLOAT, 3}, {0, TYPE_TEXCOORD, FORMAT_FLOAT, 2}, /* {0, TYPE_NORMAL, FORMAT_FLOAT, 3}, {0, TYPE_TEXCOORD, FORMAT_FLOAT, 3},//??? {0, TYPE_TEXCOORD, FORMAT_FLOAT, 2}, {0, TYPE_TEXCOORD, FORMAT_FLOAT, 4},//??? {0, TYPE_TEXCOORD, FORMAT_FLOAT, 4}//??? */ #endif }; //mr->m_DefaultVertexDecl = IRenderer::GetRendererInstance()->addVertexFormat(Fmt, elementsOf(Fmt), mr->m_piDefaultEffect);//??? #endif } if(0)//-1== mr->m_piMaterialEffect) { // get the name of the material and use it in the log message if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_NAME,&szPath) && '\0' != szPath.data[0]) { std::string sz = "[ERROR] Unable to load material: "; sz.append(szPath.data); //CLogDisplay::Instance().AddEntry(sz); } else { //CLogDisplay::Instance().AddEntry("Unable to load material: UNNAMED"); } return 0; } else { /* // use Fixed Function effect when working with shaderless cards if( mr->m_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0)) { ////LOG_PRINT("mr->m_piDefaultEffect=%d\n",mr->m_piDefaultEffect); IRenderer::GetRendererInstance()->SetTechnique( MaterialFX_FFh); }*/ } // if( piBuffer) piBuffer->Release(); LOG_FNLN; LOG_PRINT("ShaderName=%d\n",mr->m_szShaderName.c_str()); ShaderID shd = MeshRendererShadersFactory::GetShader(mr->m_szShaderName.c_str(), "main", "main"); IRenderer::GetRendererInstance()->setShader(shd); // now commit all constants to the shader // // This is not necessary for shared shader. Shader constants for // shared shaders are automatically recommited before the shader // is being used for a particular mesh if (1.0f != pcMesh->fOpacity) { //???IRenderer::GetRendererInstance()->SetFloat("TRANSPARENCY",pcMesh->fOpacity); } if (pcMesh->eShadingMode != aiShadingMode_Gouraud && !mr->m_sOptions.bNoSpecular) { IRenderer::GetRendererInstance()->SetFloat("SPECULARITY",pcMesh->fShininess);//??? IRenderer::GetRendererInstance()->SetFloat("SPECULAR_STRENGTH",pcMesh->fSpecularStrength); } IRenderer::GetRendererInstance()->SetVector("DIFFUSE_COLOR",&pcMesh->vDiffuseColor); //IRenderer::GetRendererInstance()->SetVector("SPECULAR_COLOR",&pcMesh->vSpecularColor); IRenderer::GetRendererInstance()->SetVector("AMBIENT_COLOR",&pcMesh->vAmbientColor); IRenderer::GetRendererInstance()->SetVector("EMISSIVE_COLOR",&pcMesh->vEmissiveColor); if (pcMesh->piDiffuseTexture!=-1) { IRenderer::GetRendererInstance()->SetTexture("DIFFUSE_SAMPLER",pcMesh->piDiffuseTexture); } if (pcMesh->piOpacityTexture!=-1) { IRenderer::GetRendererInstance()->SetTexture("OPACITY_SAMPLER",pcMesh->piOpacityTexture); } if (pcMesh->piSpecularTexture!=-1) { IRenderer::GetRendererInstance()->SetTexture("SPECULAR_SAMPLER",pcMesh->piSpecularTexture); } if (pcMesh->piAmbientTexture!=-1) { IRenderer::GetRendererInstance()->SetTexture("AMBIENT_SAMPLER",pcMesh->piAmbientTexture); } if (pcMesh->piEmissiveTexture!=-1) { IRenderer::GetRendererInstance()->SetTexture("EMISSIVE_SAMPLER",pcMesh->piEmissiveTexture); } if (pcMesh->piNormalTexture!=-1) { IRenderer::GetRendererInstance()->SetTexture("NORMAL_SAMPLER",pcMesh->piNormalTexture); } if (pcMesh->piShininessTexture!=-1) { IRenderer::GetRendererInstance()->SetTexture("SHININESS_SAMPLER",pcMesh->piShininessTexture); } if (pcMesh->piLightmapTexture!=-1) { IRenderer::GetRendererInstance()->SetTexture("LIGHTMAP_SAMPLER",pcMesh->piLightmapTexture); } /* if (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode()){ IRenderer::GetRendererInstance()->SetTexture("lw_tex_envmap",CBackgroundPainter::Instance().GetTexture()); }*/ #endif return 1; }
//------------------------------------------------------------------------------- int CMaterialManager::CreateMaterial( AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource) { ai_assert(NULL != pcMesh); ai_assert(NULL != pcSource); ID3DXBuffer* piBuffer; D3DXMACRO sMacro[64]; // extract all properties from the ASSIMP material structure const aiMaterial* pcMat = g_pcAsset->pcScene->mMaterials[pcSource->mMaterialIndex]; // // DIFFUSE COLOR -------------------------------------------------- // if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_DIFFUSE, (aiColor4D*)&pcMesh->vDiffuseColor)) { pcMesh->vDiffuseColor.x = 1.0f; pcMesh->vDiffuseColor.y = 1.0f; pcMesh->vDiffuseColor.z = 1.0f; pcMesh->vDiffuseColor.w = 1.0f; } // // SPECULAR COLOR -------------------------------------------------- // if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_SPECULAR, (aiColor4D*)&pcMesh->vSpecularColor)) { pcMesh->vSpecularColor.x = 1.0f; pcMesh->vSpecularColor.y = 1.0f; pcMesh->vSpecularColor.z = 1.0f; pcMesh->vSpecularColor.w = 1.0f; } // // AMBIENT COLOR -------------------------------------------------- // if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_AMBIENT, (aiColor4D*)&pcMesh->vAmbientColor)) { pcMesh->vAmbientColor.x = 0.0f; pcMesh->vAmbientColor.y = 0.0f; pcMesh->vAmbientColor.z = 0.0f; pcMesh->vAmbientColor.w = 1.0f; } // // EMISSIVE COLOR ------------------------------------------------- // if(AI_SUCCESS != aiGetMaterialColor(pcMat,AI_MATKEY_COLOR_EMISSIVE, (aiColor4D*)&pcMesh->vEmissiveColor)) { pcMesh->vEmissiveColor.x = 0.0f; pcMesh->vEmissiveColor.y = 0.0f; pcMesh->vEmissiveColor.z = 0.0f; pcMesh->vEmissiveColor.w = 1.0f; } // // Opacity -------------------------------------------------------- // if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_OPACITY,&pcMesh->fOpacity)) { pcMesh->fOpacity = 1.0f; } // // Shading Model -------------------------------------------------- // bool bDefault = false; if(AI_SUCCESS != aiGetMaterialInteger(pcMat,AI_MATKEY_SHADING_MODEL,(int*)&pcMesh->eShadingMode )) { bDefault = true; pcMesh->eShadingMode = aiShadingMode_Gouraud; } // // Shininess ------------------------------------------------------ // if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_SHININESS,&pcMesh->fShininess)) { // assume 15 as default shininess pcMesh->fShininess = 15.0f; } else if (bDefault)pcMesh->eShadingMode = aiShadingMode_Phong; // // Shininess strength ------------------------------------------------------ // if(AI_SUCCESS != aiGetMaterialFloat(pcMat,AI_MATKEY_SHININESS_STRENGTH,&pcMesh->fSpecularStrength)) { // assume 1.0 as default shininess strength pcMesh->fSpecularStrength = 1.0f; } aiString szPath; aiTextureMapMode mapU(aiTextureMapMode_Wrap),mapV(aiTextureMapMode_Wrap); bool bib =false; if (pcSource->mTextureCoords[0]) { // // DIFFUSE TEXTURE ------------------------------------------------ // if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_DIFFUSE(0),&szPath)) { LoadTexture(&pcMesh->piDiffuseTexture,&szPath); aiGetMaterialInteger(pcMat,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0),(int*)&mapU); aiGetMaterialInteger(pcMat,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0),(int*)&mapV); } // // SPECULAR TEXTURE ------------------------------------------------ // if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SPECULAR(0),&szPath)) { LoadTexture(&pcMesh->piSpecularTexture,&szPath); } // // OPACITY TEXTURE ------------------------------------------------ // if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_OPACITY(0),&szPath)) { LoadTexture(&pcMesh->piOpacityTexture,&szPath); } else { int flags = 0; aiGetMaterialInteger(pcMat,AI_MATKEY_TEXFLAGS_DIFFUSE(0),&flags); // try to find out whether the diffuse texture has any // non-opaque pixels. If we find a few, use it as opacity texture if (pcMesh->piDiffuseTexture && !(flags & aiTextureFlags_IgnoreAlpha) && HasAlphaPixels(pcMesh->piDiffuseTexture)) { int iVal; // NOTE: This special value is set by the tree view if the user // manually removes the alpha texture from the view ... if (AI_SUCCESS != aiGetMaterialInteger(pcMat,"no_a_from_d",0,0,&iVal)) { pcMesh->piOpacityTexture = pcMesh->piDiffuseTexture; pcMesh->piOpacityTexture->AddRef(); } } } // // AMBIENT TEXTURE ------------------------------------------------ // if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_AMBIENT(0),&szPath)) { LoadTexture(&pcMesh->piAmbientTexture,&szPath); } // // EMISSIVE TEXTURE ------------------------------------------------ // if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_EMISSIVE(0),&szPath)) { LoadTexture(&pcMesh->piEmissiveTexture,&szPath); } // // Shininess TEXTURE ------------------------------------------------ // if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_SHININESS(0),&szPath)) { LoadTexture(&pcMesh->piShininessTexture,&szPath); } // // Lightmap TEXTURE ------------------------------------------------ // if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_LIGHTMAP(0),&szPath)) { LoadTexture(&pcMesh->piLightmapTexture,&szPath); } // // NORMAL/HEIGHT MAP ------------------------------------------------ // bool bHM = false; if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_NORMALS(0),&szPath)) { LoadTexture(&pcMesh->piNormalTexture,&szPath); } else { if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_TEXTURE_HEIGHT(0),&szPath)) { LoadTexture(&pcMesh->piNormalTexture,&szPath); } else bib = true; bHM = true; } // normal/height maps are sometimes mixed up. Try to detect the type // of the texture automatically if (pcMesh->piNormalTexture) { HMtoNMIfNecessary(pcMesh->piNormalTexture, &pcMesh->piNormalTexture,bHM); } } // check whether a global background texture is contained // in this material. Some loaders set this value ... if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_GLOBAL_BACKGROUND_IMAGE,&szPath)) { CBackgroundPainter::Instance().SetTextureBG(szPath.data); } // BUGFIX: If the shininess is 0.0f disable phong lighting // This is a workaround for some meshes in the DX SDK (e.g. tiny.x) // FIX: Added this check to the x-loader, but the line remains to // catch other loader doing the same ... if (0.0f == pcMesh->fShininess){ pcMesh->eShadingMode = aiShadingMode_Gouraud; } int two_sided = 0; aiGetMaterialInteger(pcMat,AI_MATKEY_TWOSIDED,&two_sided); pcMesh->twosided = (two_sided != 0); // check whether we have already a material using the same // shader. This will decrease loading time rapidly ... for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i) { if (g_pcAsset->pcScene->mMeshes[i] == pcSource) { break; } AssetHelper::MeshHelper* pc = g_pcAsset->apcMeshes[i]; if ((pcMesh->piDiffuseTexture != NULL ? true : false) != (pc->piDiffuseTexture != NULL ? true : false)) continue; if ((pcMesh->piSpecularTexture != NULL ? true : false) != (pc->piSpecularTexture != NULL ? true : false)) continue; if ((pcMesh->piAmbientTexture != NULL ? true : false) != (pc->piAmbientTexture != NULL ? true : false)) continue; if ((pcMesh->piEmissiveTexture != NULL ? true : false) != (pc->piEmissiveTexture != NULL ? true : false)) continue; if ((pcMesh->piNormalTexture != NULL ? true : false) != (pc->piNormalTexture != NULL ? true : false)) continue; if ((pcMesh->piOpacityTexture != NULL ? true : false) != (pc->piOpacityTexture != NULL ? true : false)) continue; if ((pcMesh->piShininessTexture != NULL ? true : false) != (pc->piShininessTexture != NULL ? true : false)) continue; if ((pcMesh->piLightmapTexture != NULL ? true : false) != (pc->piLightmapTexture != NULL ? true : false)) continue; if ((pcMesh->eShadingMode != aiShadingMode_Gouraud ? true : false) != (pc->eShadingMode != aiShadingMode_Gouraud ? true : false)) continue; if ((pcMesh->fOpacity != 1.0f ? true : false) != (pc->fOpacity != 1.0f ? true : false)) continue; if (pcSource->HasBones() != g_pcAsset->pcScene->mMeshes[i]->HasBones()) continue; // we can reuse this material if (pc->piEffect) { pcMesh->piEffect = pc->piEffect; pc->bSharedFX = pcMesh->bSharedFX = true; pcMesh->piEffect->AddRef(); return 2; } } m_iShaderCount++; // build macros for the HLSL compiler unsigned int iCurrent = 0; if (pcMesh->piDiffuseTexture) { sMacro[iCurrent].Name = "AV_DIFFUSE_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; if (mapU == aiTextureMapMode_Wrap) sMacro[iCurrent].Name = "AV_WRAPU"; else if (mapU == aiTextureMapMode_Mirror) sMacro[iCurrent].Name = "AV_MIRRORU"; else // if (mapU == aiTextureMapMode_Clamp) sMacro[iCurrent].Name = "AV_CLAMPU"; sMacro[iCurrent].Definition = "1"; ++iCurrent; if (mapV == aiTextureMapMode_Wrap) sMacro[iCurrent].Name = "AV_WRAPV"; else if (mapV == aiTextureMapMode_Mirror) sMacro[iCurrent].Name = "AV_MIRRORV"; else // if (mapV == aiTextureMapMode_Clamp) sMacro[iCurrent].Name = "AV_CLAMPV"; sMacro[iCurrent].Definition = "1"; ++iCurrent; } if (pcMesh->piSpecularTexture) { sMacro[iCurrent].Name = "AV_SPECULAR_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; } if (pcMesh->piAmbientTexture) { sMacro[iCurrent].Name = "AV_AMBIENT_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; } if (pcMesh->piEmissiveTexture) { sMacro[iCurrent].Name = "AV_EMISSIVE_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; } char buff[32]; if (pcMesh->piLightmapTexture) { sMacro[iCurrent].Name = "AV_LIGHTMAP_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; int idx; if(AI_SUCCESS == aiGetMaterialInteger(pcMat,AI_MATKEY_UVWSRC_LIGHTMAP(0),&idx) && idx >= 1 && pcSource->mTextureCoords[idx]) { sMacro[iCurrent].Name = "AV_TWO_UV"; sMacro[iCurrent].Definition = "1"; ++iCurrent; sMacro[iCurrent].Definition = "IN.TexCoord1"; } else sMacro[iCurrent].Definition = "IN.TexCoord0"; sMacro[iCurrent].Name = "AV_LIGHTMAP_TEXTURE_UV_COORD"; ++iCurrent;float f= 1.f; aiGetMaterialFloat(pcMat,AI_MATKEY_TEXBLEND_LIGHTMAP(0),&f); sprintf(buff,"%f",f); sMacro[iCurrent].Name = "LM_STRENGTH"; sMacro[iCurrent].Definition = buff; ++iCurrent; } if (pcMesh->piNormalTexture && !bib) { sMacro[iCurrent].Name = "AV_NORMAL_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; } if (pcMesh->piOpacityTexture) { sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; if (pcMesh->piOpacityTexture == pcMesh->piDiffuseTexture) { sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE_REGISTER_MASK"; sMacro[iCurrent].Definition = "a"; ++iCurrent; } else { sMacro[iCurrent].Name = "AV_OPACITY_TEXTURE_REGISTER_MASK"; sMacro[iCurrent].Definition = "r"; ++iCurrent; } } if (pcMesh->eShadingMode != aiShadingMode_Gouraud && !g_sOptions.bNoSpecular) { sMacro[iCurrent].Name = "AV_SPECULAR_COMPONENT"; sMacro[iCurrent].Definition = "1"; ++iCurrent; if (pcMesh->piShininessTexture) { sMacro[iCurrent].Name = "AV_SHININESS_TEXTURE"; sMacro[iCurrent].Definition = "1"; ++iCurrent; } } if (1.0f != pcMesh->fOpacity) { sMacro[iCurrent].Name = "AV_OPACITY"; sMacro[iCurrent].Definition = "1"; ++iCurrent; } if( pcSource->HasBones()) { sMacro[iCurrent].Name = "AV_SKINNING"; sMacro[iCurrent].Definition = "1"; ++iCurrent; } // If a cubemap is active, we'll need to lookup it for calculating // a physically correct reflection if (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode()) { sMacro[iCurrent].Name = "AV_SKYBOX_LOOKUP"; sMacro[iCurrent].Definition = "1"; ++iCurrent; } sMacro[iCurrent].Name = NULL; sMacro[iCurrent].Definition = NULL; // compile the shader if(FAILED( D3DXCreateEffect(g_piDevice, g_szMaterialShader.c_str(),(UINT)g_szMaterialShader.length(), (const D3DXMACRO*)sMacro,NULL,0,NULL,&pcMesh->piEffect,&piBuffer))) { // failed to compile the shader if( piBuffer) { MessageBox(g_hDlg,(LPCSTR)piBuffer->GetBufferPointer(),"HLSL",MB_OK); piBuffer->Release(); } // use the default material instead if (g_piDefaultEffect) { pcMesh->piEffect = g_piDefaultEffect; g_piDefaultEffect->AddRef(); } // get the name of the material and use it in the log message if(AI_SUCCESS == aiGetMaterialString(pcMat,AI_MATKEY_NAME,&szPath) && '\0' != szPath.data[0]) { std::string sz = "[ERROR] Unable to load material: "; sz.append(szPath.data); CLogDisplay::Instance().AddEntry(sz); } else { CLogDisplay::Instance().AddEntry("Unable to load material: UNNAMED"); } return 0; } else { // use Fixed Function effect when working with shaderless cards if( g_sCaps.PixelShaderVersion < D3DPS_VERSION(2,0)) pcMesh->piEffect->SetTechnique( "MaterialFX_FF"); } if( piBuffer) piBuffer->Release(); // now commit all constants to the shader // // This is not necessary for shared shader. Shader constants for // shared shaders are automatically recommited before the shader // is being used for a particular mesh if (1.0f != pcMesh->fOpacity) pcMesh->piEffect->SetFloat("TRANSPARENCY",pcMesh->fOpacity); if (pcMesh->eShadingMode != aiShadingMode_Gouraud && !g_sOptions.bNoSpecular) { pcMesh->piEffect->SetFloat("SPECULARITY",pcMesh->fShininess); pcMesh->piEffect->SetFloat("SPECULAR_STRENGTH",pcMesh->fSpecularStrength); } pcMesh->piEffect->SetVector("DIFFUSE_COLOR",&pcMesh->vDiffuseColor); pcMesh->piEffect->SetVector("SPECULAR_COLOR",&pcMesh->vSpecularColor); pcMesh->piEffect->SetVector("AMBIENT_COLOR",&pcMesh->vAmbientColor); pcMesh->piEffect->SetVector("EMISSIVE_COLOR",&pcMesh->vEmissiveColor); if (pcMesh->piDiffuseTexture) pcMesh->piEffect->SetTexture("DIFFUSE_TEXTURE",pcMesh->piDiffuseTexture); if (pcMesh->piOpacityTexture) pcMesh->piEffect->SetTexture("OPACITY_TEXTURE",pcMesh->piOpacityTexture); if (pcMesh->piSpecularTexture) pcMesh->piEffect->SetTexture("SPECULAR_TEXTURE",pcMesh->piSpecularTexture); if (pcMesh->piAmbientTexture) pcMesh->piEffect->SetTexture("AMBIENT_TEXTURE",pcMesh->piAmbientTexture); if (pcMesh->piEmissiveTexture) pcMesh->piEffect->SetTexture("EMISSIVE_TEXTURE",pcMesh->piEmissiveTexture); if (pcMesh->piNormalTexture) pcMesh->piEffect->SetTexture("NORMAL_TEXTURE",pcMesh->piNormalTexture); if (pcMesh->piShininessTexture) pcMesh->piEffect->SetTexture("SHININESS_TEXTURE",pcMesh->piShininessTexture); if (pcMesh->piLightmapTexture) pcMesh->piEffect->SetTexture("LIGHTMAP_TEXTURE",pcMesh->piLightmapTexture); if (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode()){ pcMesh->piEffect->SetTexture("lw_tex_envmap",CBackgroundPainter::Instance().GetTexture()); } return 1; }
//! Loads and returns a skinned model from a file. SkinnedModel* ModelImporter::LoadSkinnedModel(string filename) { // Is the model already loaded? if(mSkinnedModelMap.find(filename) != mSkinnedModelMap.end()) return mSkinnedModelMap[filename]; Assimp::Importer importer; mFilename = filename; SkinnedModel* model = NULL; // Important! Makes sure that if the angle between two face normals is > 80 they are not smoothed together. // Since the angle between a cubes face normals is 90 the lighting looks very bad if we don't specify this. importer.SetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, 80.0f); importer.SetPropertyInteger(AI_CONFIG_IMPORT_TER_MAKE_UVS, 1); importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_LINE); // Load scene from the file. const aiScene* scene = importer.ReadFile(filename, aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_SplitLargeMeshes | aiProcess_ConvertToLeftHanded | aiProcess_SortByPType); if(scene) { // Create the model that is getting filled out. model = new SkinnedModel(); // Create the animator. SceneAnimator* animator = new SceneAnimator(); animator->Init(scene); model->SetAnimator(animator); // Loop through all meshes. for(int j = 0; j < scene->mNumMeshes; j++) { aiMesh* assimpMesh = scene->mMeshes[j]; // Calculate vertex weight and bone indices. vector<Weights> weights = CalculateWeights(assimpMesh, animator); vector<SkinnedVertex> vertices; vector<UINT> indices; // Add vertices to the vertex list. for(int i = 0; i < assimpMesh->mNumVertices; i++) { aiVector3D v = assimpMesh->mVertices[i]; aiVector3D n = assimpMesh->mNormals[i]; aiVector3D t = aiVector3D(0, 0, 0); if(assimpMesh->HasTextureCoords(0)) t = assimpMesh->mTextureCoords[0][i]; n = n.Normalize(); // Pos, normal and texture coordinates. SkinnedVertex vertex(v.x, v.y, v.z, n.x, n.y, n.z, 0, 0, 1, t.x, t.y); // Bone indices and weights. for(int k = 0; k < weights[i].boneIndices.size(); k++) vertex.BoneIndices[k] = weights[i].boneIndices[k]; vertex.Weights.x = weights[i].weights.size() >= 1 ? weights[i].weights[0] : 0; vertex.Weights.y = weights[i].weights.size() >= 2 ? weights[i].weights[1] : 0; vertex.Weights.z = weights[i].weights.size() >= 3 ? weights[i].weights[2] : 0; vertices.push_back(vertex); } // Add indices to the index list. for(int i = 0; i < assimpMesh->mNumFaces; i++) for(int k = 0; k < assimpMesh->mFaces[i].mNumIndices; k++) indices.push_back(assimpMesh->mFaces[i].mIndices[k]); // Get the path to the texture in the directory. aiString path; aiMaterial* material = scene->mMaterials[assimpMesh->mMaterialIndex]; material->Get(AI_MATKEY_TEXTURE_DIFFUSE(0), path); FindValidPath(&path); // Extract all the ambient, diffuse and specular colors. aiColor4D ambient, diffuse, specular; material->Get(AI_MATKEY_COLOR_AMBIENT, ambient); material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse); material->Get(AI_MATKEY_COLOR_SPECULAR, specular); // Create the mesh and its primitive. SkinnedMesh* mesh = new SkinnedMesh(); Primitive* primitive = new Primitive(GlobalApp::GetD3DDevice(), vertices, indices); mesh->SetPrimitive(primitive); mesh->SetVertices(vertices); mesh->SetIndices(indices); mPrimtiveFactory->AddPrimitive(path.C_Str(), primitive); // Replace .tga with .bmp [HACK]. string texturePath = path.C_Str(); int tgaPos = texturePath.find_first_of(".tga"); if(tgaPos != string::npos) { texturePath.replace(texturePath.size()-4, 4, ".bmp"); path = texturePath; } // Any texture? if(_stricmp(path.C_Str(), "") != 0) mesh->LoadTexture(path.C_Str()); // Any normal map? aiString nmap; material->Get(AI_MATKEY_TEXTURE_HEIGHT(0), nmap); FindValidPath(&nmap); if(_stricmp(nmap.C_Str(), "") != 0) mesh->SetNormalMap(GlobalApp::GetGraphics()->LoadTexture(nmap.C_Str())); // [NOTE] The material is set to white. mesh->SetMaterial(Material(Colors::White)); //mesh->SetMaterial(Material(diffuse, diffuse, diffuse)); model->SetFilename(filename); // Add the mesh to the model. model->AddMesh(mesh); } // Pre-calculate the bounding box. model->CalculateAABB(); // Add the newly created mesh to the map and return it. mSkinnedModelMap[filename] = model; return mSkinnedModelMap[filename]; } else { char buffer[246]; sprintf(buffer, "Error loading model: %s", filename.c_str()); MessageBox(0, buffer, "Error!", 0); mSkinnedModelMap[filename] = LoadSkinnedModel("models/box.obj"); return mSkinnedModelMap[filename]; } }
//! Loads and returns a static model from a file. StaticModel* ModelImporter::LoadStaticModel(string filename) { // Is the model already loaded? if(mStaticModelMap.find(filename) != mStaticModelMap.end()) return mStaticModelMap[filename]; Assimp::Importer importer; mFilename = filename; StaticModel* model = NULL; // Important! Makes sure that if the angle between two face normals is > 80 they are not smoothed together. // Since the angle between a cubes face normals is 90 the lighting looks very bad if we don't specify this. importer.SetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE, 80.0f); importer.SetPropertyInteger(AI_CONFIG_IMPORT_TER_MAKE_UVS, 1); importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_LINE); // Load scene from the file. const aiScene* scene = importer.ReadFile(filename, aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_SplitLargeMeshes | aiProcess_ConvertToLeftHanded | aiProcess_SortByPType); // Successfully loaded the scene. if(scene) { // Create the model that is getting filled out. model = new StaticModel(); // Loop through all meshes. for(int i = 0; i < scene->mNumMeshes; i++) { aiMesh* assimpMesh = scene->mMeshes[i]; vector<Vertex> vertices; vector<UINT> indices; // Add vertices to the vertex list. for(int i = 0; i < assimpMesh->mNumVertices; i++) { aiVector3D v = assimpMesh->mVertices[i]; aiVector3D n = assimpMesh->mNormals[i]; aiVector3D t = aiVector3D(0, 0, 0); if(assimpMesh->HasTextureCoords(0)) t = assimpMesh->mTextureCoords[0][i]; n = n.Normalize(); Vertex vertex(v.x, v.y, v.z, n.x, n.y, n.z, 0, 0, 0, t.x, t.y); vertices.push_back(vertex); } // Add indices to the index list. for(int i = 0; i < assimpMesh->mNumFaces; i++) for(int j = 0; j < assimpMesh->mFaces[i].mNumIndices; j++) indices.push_back(assimpMesh->mFaces[i].mIndices[j]); // Get the path to the texture in the directory. aiString path; aiMaterial* material = scene->mMaterials[assimpMesh->mMaterialIndex]; material->Get(AI_MATKEY_TEXTURE_DIFFUSE(0), path); FindValidPath(&path); // Extract all the ambient, diffuse and specular colors. aiColor4D ambient, diffuse, specular; material->Get(AI_MATKEY_COLOR_AMBIENT, ambient); material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse); material->Get(AI_MATKEY_COLOR_SPECULAR, specular); // Create the mesh and its primitive. StaticMesh* mesh = new StaticMesh(); Primitive* primitive = new Primitive(GlobalApp::GetD3DDevice(), vertices, indices); mesh->SetPrimitive(primitive); mesh->SetVertices(vertices); mesh->SetIndices(indices); mPrimtiveFactory->AddPrimitive(path.C_Str(), primitive); // Any texture? if(_stricmp(path.C_Str(), "") != 0) mesh->LoadTexture(path.C_Str()); // Any normal map? aiString nmap; material->Get(AI_MATKEY_TEXTURE_HEIGHT(0), nmap); FindValidPath(&nmap); if(_stricmp(nmap.C_Str(), "") != 0) mesh->SetNormalMap(GlobalApp::GetGraphics()->LoadTexture(nmap.C_Str())); // [NOTE] The material is set to white. mesh->SetMaterial(Material(Colors::White)); // Was before [NOTE] model->SetFilename(filename); // Add the mesh to the model. model->AddMesh(mesh); } // Add to the model map and return it. mStaticModelMap[filename] = model; return mStaticModelMap[filename]; } else { char buffer[246]; sprintf(buffer, "Error loading model: %s", filename.c_str()); MessageBox(0, buffer, "Error!", 0); mStaticModelMap[filename] = LoadStaticModel("models/box.obj"); return mStaticModelMap[filename]; } }
HRESULT Mesh::Create(ID3D11Device * pDevice, const char * path, const char * name, bool sdkmesh) { m_isSdkMesh = sdkmesh; if (sdkmesh) { char filename[256]; sprintf(filename, "%s%s", path, name); std::string fname(filename); std::wstring wfname(fname.begin(), fname.end()); return m_sdkMesh.Create(pDevice, wfname.c_str(), false); } #ifdef AMD_SDK_MINIMAL else { // the minimal-dependencies version of AMD_SDK // only supports sdkmesh return E_FAIL; } #else HRESULT hr = S_OK; Assimp::Importer importer; int num_vertices = 0; int num_faces = 0; std::string filename = std::string(path) + std::string(name); aiScene* scene = (aiScene*)importer.ReadFile(filename.c_str(), 0); if (!scene) { return E_FAIL; } _id = crcFast((const unsigned char *)filename.c_str(), (int)filename.length()); if (scene->HasMeshes() && scene->mNumMeshes > 0) { for (int i = 0; i < (int)scene->mNumMeshes; i++) { num_vertices += scene->mMeshes[i]->mNumVertices; num_faces += scene->mMeshes[i]->mNumFaces; } if (num_vertices == 0 || num_faces == 0) { return S_OK; } int current_vertex = 0; int current_face = 0; _material_group.resize(scene->mNumMeshes); _vertex.resize(num_vertices); _index.resize(num_faces * 3); ID3D11DeviceContext * pContext = NULL; pDevice->GetImmediateContext(&pContext); for (unsigned int i = 0; i < scene->mNumMeshes; i++) { ID3D11Texture2D * t2d = NULL; ID3D11ShaderResourceView * srv = NULL; aiMesh * mesh = scene->mMeshes[i]; aiMaterial * material = scene->mMaterials[mesh->mMaterialIndex]; aiString c_texture_filename; material->Get(AI_MATKEY_TEXTURE_DIFFUSE(0), c_texture_filename); std::string tex_filename = std::string(path) + std::string(c_texture_filename.C_Str()); { WCHAR wc_texture_filename[1024]; mbstowcs(wc_texture_filename, tex_filename.c_str(), tex_filename.length() + 1); unsigned int bind_flags = D3D11_BIND_SHADER_RESOURCE; hr = DirectX::CreateDDSTextureFromFileEx(pDevice, wc_texture_filename, 0, D3D11_USAGE_DEFAULT, bind_flags, 0, 0, true, (ID3D11Resource**)&t2d, &srv); } _material_group[i]._texture_index = (int)_t2d.size(); _t2d.push_back(t2d); _srv.push_back(srv); _material_group[i]._first_index = current_face; _material_group[i]._index_count = mesh->mNumFaces * 3; aiVector3D * position = mesh->HasPositions() ? mesh->mVertices : NULL; aiVector3D * normal = mesh->HasNormals() ? mesh->mNormals : NULL; aiVector3D * uv = mesh->HasTextureCoords(0) ? mesh->mTextureCoords[0] : NULL; for (unsigned int j = 0; j < mesh->mNumVertices; j++) { if (position != NULL) { memcpy( &_vertex[current_vertex + j].position, &position[j], sizeof( float ) * 3 ); } if (normal != NULL) { memcpy( &_vertex[current_vertex + j].normal, &normal[j], sizeof( float ) * 3 ); } if (uv != NULL) { memcpy( &_vertex[current_vertex + j].uv, &uv[j], sizeof( float ) * 2 ); } } if (mesh->HasFaces()) { aiFace * f = mesh->mFaces; for (unsigned int j = 0; j < mesh->mNumFaces; j++) { _index[current_face + j * 3 + 0] = current_vertex + f[j].mIndices[0]; _index[current_face + j * 3 + 1] = current_vertex + f[j].mIndices[1]; _index[current_face + j * 3 + 2] = current_vertex + f[j].mIndices[2]; } } current_face += mesh->mNumFaces * 3; current_vertex += mesh->mNumVertices; } AMD_SAFE_RELEASE(pContext); CD3D11_BUFFER_DESC vertexDesc, indexDesc; vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_SHADER_RESOURCE; vertexDesc.ByteWidth = sizeof(Vertex) * num_vertices; vertexDesc.CPUAccessFlags = 0; vertexDesc.MiscFlags = 0; vertexDesc.StructureByteStride = 0; vertexDesc.Usage = D3D11_USAGE_IMMUTABLE; indexDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; indexDesc.ByteWidth = sizeof(int) * num_faces * 3; indexDesc.CPUAccessFlags = 0; indexDesc.MiscFlags = 0; indexDesc.StructureByteStride = 0; indexDesc.Usage = D3D11_USAGE_IMMUTABLE; D3D11_SUBRESOURCE_DATA vertexData, indexData; memset(&vertexData, 0, sizeof(vertexData)); memset(&indexData, 0, sizeof(indexData)); vertexData.pSysMem = &_vertex[0]; indexData.pSysMem = &_index[0]; hr = pDevice->CreateBuffer(&vertexDesc, &vertexData, &_b1d_vertex); hr = pDevice->CreateBuffer(&indexDesc, &indexData, &_b1d_index); } return hr; #endif }
void OBJWriter::write(const std::shared_ptr<gameplay::Model>& model, const std::string& baseName, const std::map<loader::TextureLayoutProxy::TextureKey, std::shared_ptr<gameplay::Material>>& mtlMap1, const std::map<loader::TextureLayoutProxy::TextureKey, std::shared_ptr<gameplay::Material>>& mtlMap2, const glm::vec3& ambientColor) const { Expects(model != nullptr); auto fullPath = m_basePath / baseName; Assimp::Exporter exporter; std::string formatIdentifier; for(size_t i = 0; i < exporter.GetExportFormatCount(); ++i) { auto descr = exporter.GetExportFormatDescription(i); BOOST_ASSERT(descr != nullptr); std::string exporterExtension = std::string(".") + descr->fileExtension; if(exporterExtension == fullPath.extension().string()) { formatIdentifier = descr->id; break; } } if(formatIdentifier.empty()) { BOOST_LOG_TRIVIAL(error) << "Failed to find an exporter for the supplied file extension"; BOOST_LOG_TRIVIAL(info) << "Here's the list of registered exporters"; for(size_t i = 0; i < exporter.GetExportFormatCount(); ++i) { auto descr = exporter.GetExportFormatDescription(i); BOOST_ASSERT(descr != nullptr); BOOST_LOG_TRIVIAL(info) << descr->description << ", extension `" << descr->fileExtension << "`, id `" << descr->id << "`"; } BOOST_THROW_EXCEPTION(std::runtime_error("Failed to find an exporter for the supplied file extension")); } std::unique_ptr<aiScene> scene = std::make_unique<aiScene>(); BOOST_ASSERT(scene->mRootNode == nullptr); scene->mRootNode = new aiNode(); { size_t totalPartCount = 0; for( const auto& mesh : model->getMeshes() ) { totalPartCount += mesh->getPartCount(); } scene->mNumMaterials = totalPartCount; scene->mMaterials = new aiMaterial*[totalPartCount]; std::fill_n(scene->mMaterials, totalPartCount, nullptr); scene->mNumMeshes = totalPartCount; scene->mMeshes = new aiMesh*[totalPartCount]; std::fill_n(scene->mMeshes, totalPartCount, nullptr); scene->mRootNode->mNumMeshes = totalPartCount; scene->mRootNode->mMeshes = new unsigned int[totalPartCount]; for( size_t i = 0; i < totalPartCount; ++i ) scene->mRootNode->mMeshes[i] = i; } for( size_t mi = 0, globalPartIndex = 0; mi < model->getMeshes().size(); ++mi ) { BOOST_ASSERT(mi < scene->mNumMeshes); const auto& mesh = model->getMeshes()[mi]; for( size_t pi = 0; pi < mesh->getPartCount(); ++pi , ++globalPartIndex ) { BOOST_ASSERT(globalPartIndex < scene->mNumMaterials); const std::shared_ptr<gameplay::MeshPart>& part = mesh->getPart(pi); scene->mMeshes[globalPartIndex] = new aiMesh(); aiMesh* outMesh = scene->mMeshes[globalPartIndex]; allocateElementMemory(mesh, outMesh); copyVertexData(mesh, outMesh); BOOST_ASSERT(part->getPrimitiveType() == gameplay::Mesh::PrimitiveType::TRIANGLES && part->getIndexCount() % 3 == 0); outMesh->mMaterialIndex = globalPartIndex; scene->mMaterials[globalPartIndex] = new aiMaterial(); scene->mMaterials[globalPartIndex]->AddProperty(new aiColor4D(ambientColor.r, ambientColor.g, ambientColor.b, 1), 1, AI_MATKEY_COLOR_AMBIENT); { // try to find the texture for our material using Entry = decltype(*mtlMap1.begin()); auto finder = [&part](const Entry& entry) { return entry.second == part->getMaterial(); }; auto texIt = std::find_if(mtlMap1.begin(), mtlMap1.end(), finder); bool found = false; if( texIt != mtlMap1.end() ) { scene->mMaterials[globalPartIndex]->AddProperty(new aiString(makeTextureName(texIt->first.tileAndFlag & TextureIndexMask) + ".png"), AI_MATKEY_TEXTURE_DIFFUSE(0)); found = true; } if( !found ) { texIt = std::find_if(mtlMap2.begin(), mtlMap2.end(), finder); if( texIt != mtlMap2.end() ) { scene->mMaterials[globalPartIndex]->AddProperty(new aiString(makeTextureName(texIt->first.tileAndFlag & TextureIndexMask) + ".png"), AI_MATKEY_TEXTURE_DIFFUSE(0)); } } } outMesh->mNumFaces = part->getIndexCount() / 3; outMesh->mFaces = new aiFace[outMesh->mNumFaces]; switch( part->getIndexFormat() ) { case gameplay::Mesh::INDEX8: copyIndices<uint8_t>(part, outMesh); break; case gameplay::Mesh::INDEX16: copyIndices<uint16_t>(part, outMesh); break; case gameplay::Mesh::INDEX32: copyIndices<uint32_t>(part, outMesh); break; default: break; } } } exporter.Export(scene.get(), formatIdentifier.c_str(), fullPath.string(), aiProcess_JoinIdenticalVertices | aiProcess_ValidateDataStructure | aiProcess_FlipUVs); }