static void BitmapDimensions(int &width, int &height, Texmap * map) { // int h=dim; w=dim; if(map == NULL){ //NH 05-Dec-05 This can happen when submaps are not assigned - in this case simply bail and let //the parent texture deal with it. // height = width = 0; return; } if(map->ClassID() == GNORMAL_CLASS_ID) { Texmap * bmap; map->GetParamBlock(0)->GetValue(2,0,bmap,FOREVER); // normal map BitmapDimensions(width,height,bmap); return; } else if(map->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) { BitmapTex *pBT; Bitmap *pTex; pBT = static_cast<BitmapTex *>(map); pTex = pBT->GetBitmap(0); if (pTex) { width = getClosestPowerOf2(pTex->Width()); height = getClosestPowerOf2(pTex->Height()); } return; } else{ } }
P(GmMaterial) GmUtil::createGmMaterial( Mtl* material, Mtl* bakedmaterial ) { require( material ); P(GmMaterial) s = new GmMaterial; // get name static int unnamedCount = 0; if ( material->GetName().data() ) s->name = material->GetName().data(); else s->name = "noname #"+String::valueOf( ++unnamedCount ); // Standard material (+Diffuse) (+ Reflection) if ( material->ClassID() == Class_ID(DMTL_CLASS_ID,0) ) { StdMat* stdmat = static_cast<StdMat*>(material); StdMat* bakedmat = static_cast<StdMat*>(bakedmaterial); // StdMat2? StdMat2* stdmat2 = 0; if ( stdmat->SupportsShaders() ) stdmat2 = static_cast<StdMat2*>( stdmat ); // uniform transparency s->opacity = stdmat->GetOpacity(0); // self illumination s->selfIllum = stdmat->GetSelfIllum(0); // two-sided material? s->twosided = ( 0 != stdmat->GetTwoSided() ); // blending mode s->blend = GmMaterial::BLEND_COPY; if ( s->opacity < 1.f ) s->blend = GmMaterial::BLEND_MULTIPLY; if ( stdmat->GetTransparencyType() == TRANSP_ADDITIVE ) s->blend = GmMaterial::BLEND_ADD; // diffuse color s->diffuseColor = toColorf( stdmat->GetDiffuse(0) ); // specular highlights float shinStr = stdmat->GetShinStr(0); s->specular = (shinStr > 0.f); if ( s->specular ) { float shininess = stdmat->GetShininess(0); s->specularExponent = Math::pow( 2.f, shininess*10.f + 2.f ); s->specularColor = toColorf( stdmat->GetSpecular(0) ) * shinStr; } if ( bakedmat ) { shinStr = bakedmat->GetShinStr(0); s->specular = (shinStr > 0.f); if ( s->specular ) { float shininess = bakedmat->GetShininess(0); s->specularExponent = Math::pow( 2.f, shininess*10.f + 2.f ); s->specularColor = toColorf( bakedmat->GetSpecular(0) ) * shinStr; } } // diffuse texture layer BitmapTex* tex = SceneExportUtil::getStdMatBitmapTex( stdmat, ID_DI ); if ( tex ) { GmMaterial::TextureLayer& layer = s->diffuseLayer; setLayerTex( layer, tex, s->name ); } // opacity texture layer tex = SceneExportUtil::getStdMatBitmapTex( stdmat, ID_OP ); if ( tex ) { GmMaterial::TextureLayer& layer = s->opacityLayer; setLayerTex( layer, tex, s->name ); // check alpha channel validity Bitmap* bmp = tex->GetBitmap(0); if ( bmp && !bmp->HasAlpha() ) Debug::printlnError( "Material \"{0}\" opacity map \"{1}\" must have image alpha channel.", s->name, tex->GetMapName() ); //throw IOException( Format("Material \"{0}\" opacity map \"{1}\" must have image alpha channel.", s->name, tex->GetMapName()) ); s->blend = GmMaterial::BLEND_MULTIPLY; // check that opacity map is the same as diffuse map if ( s->opacityLayer.filename != s->diffuseLayer.filename ) throw IOException( Format("Material \"{0}\" diffuse bitmap needs to be the same in opacity map.(diffuse map is \"{1}\" and opacity map is \"{2}\")", s->name, s->diffuseLayer.filename, s->opacityLayer.filename) ); if ( s->opacityLayer.coordset != s->diffuseLayer.coordset ) throw IOException( Format("Material \"{0}\" diffuse map texture coordinate set needs to be the same in opacity map.", s->name) ); if ( s->opacityLayer.env != s->diffuseLayer.env ) throw IOException( Format("Material \"{0}\" diffuse map texture coordinate generator needs to be the same in opacity map.", s->name) ); } // reflection texture layer tex = SceneExportUtil::getStdMatBitmapTex( stdmat, ID_RL ); if ( tex ) { GmMaterial::TextureLayer& layer = s->reflectionLayer; setLayerTex( layer, tex, s->name ); } // glossiness (shininess strength, SS) texture layer tex = SceneExportUtil::getStdMatBitmapTex( stdmat, ID_SS ); if ( tex ) { GmMaterial::TextureLayer& layer = s->glossinessLayer; setLayerTex( layer, tex, s->name ); // check alpha channel validity Bitmap* bmp = tex->GetBitmap(0); //if ( bmp && !bmp->HasAlpha() ) // throw IOException( Format("Material \"{0}\" glossiness map \"{1}\" must have image alpha channel.", s->name, tex->GetMapName()) ); if ( bmp && !bmp->HasAlpha() ) Debug::printlnError("Material \"{0}\" glossiness map \"{1}\" must have image alpha channel.", s->name, tex->GetMapName() ); // check that glossiness map is the same as diffuse map if ( s->glossinessLayer.filename != s->diffuseLayer.filename ) throw IOException( Format("Material \"{0}\" diffuse bitmap needs to be the same in glossiness map.(diffuse map is \"{1}\" and glossiness map is \"{2}\")", s->name, s->diffuseLayer.filename, s->glossinessLayer.filename) ); if ( s->glossinessLayer.coordset != s->diffuseLayer.coordset ) throw IOException( Format("Material \"{0}\" diffuse map texture coordinate set needs to be the same in glossiness map.", s->name) ); if ( s->glossinessLayer.env != s->diffuseLayer.env ) throw IOException( Format("Material \"{0}\" diffuse map texture coordinate generator needs to be the same in glossiness map.", s->name) ); // check that reflection map has been set if ( s->reflectionLayer.filename.length() == 0 ) throw IOException( Format("Material \"{0}\" glossiness map requires reflection map to be set.", s->name) ); } // bump texture layer tex = SceneExportUtil::getStdMatBitmapTex( stdmat, ID_BU ); if ( tex ) { GmMaterial::TextureLayer& layer = s->bumpLayer; setLayerTex( layer, tex, s->name ); } // specular color texture layer tex = SceneExportUtil::getStdMatBitmapTex( stdmat, ID_SP ); if ( tex ) { GmMaterial::TextureLayer& layer = s->specularColorLayer; setLayerTex( layer, tex, s->name ); } // specular level texture layer tex = SceneExportUtil::getStdMatBitmapTex( stdmat, ID_SH ); if ( tex ) { GmMaterial::TextureLayer& layer = s->specularLevelLayer; setLayerTex( layer, tex, s->name ); } // lightmap texture layer ( from self-illumination map of baked material ) tex = SceneExportUtil::getStdMatBitmapTex( stdmat, ID_SI ); BitmapTex* tex2 = 0; if ( bakedmat ) tex2 = SceneExportUtil::getStdMatBitmapTex( bakedmat, ID_SI ); if ( tex || tex2 ) { GmMaterial::TextureLayer& layer = s->lightMapLayer; if ( tex && !tex2 ) setLayerTex( layer, tex, s->name ); else if ( tex2 ) setLayerTex( layer, tex2, s->name ); } } return s; }
// --[ Method ]--------------------------------------------------------------- // // - Class : CStravaganzaMaxTools // // - prototype : bool BuildShaders() // // - Purpose : Builds the shader list from MAX's materials. // Preview mode requires texture files to be stored with full // path in order to load them. When we export, we only store the // filename. Another thing is that in the export mode, we copy // all textures into the path specified by the user if that // option is checked. // // ----------------------------------------------------------------------------- bool CStravaganzaMaxTools::BuildShaders() { std::vector<Mtl*>::iterator it; assert(m_vecShaders.empty()); if(!m_bPreview && m_bCopyTextures && m_strTexturePath == "") { CLogger::NotifyWindow("Textures won't be copied\nSpecify a valid output texture path first"); } LOG.Write("\n\n-Building shaders: "); for(it = m_vecMaterials.begin(); it != m_vecMaterials.end(); ++it) { Mtl* pMaxMaterial = *it; assert(pMaxMaterial); LOG.Write("\n %s", pMaxMaterial->GetName().data()); CShaderStandard* pShaderStd = new CShaderStandard; pShaderStd->SetName(pMaxMaterial->GetName().data()); // Properties StdMat2 *pMaxStandardMtl = NULL; StdMat2 *pMaxBakedMtl = NULL; float fAlpha; if(pMaxMaterial->ClassID() == Class_ID(DMTL_CLASS_ID, 0)) { pMaxStandardMtl = (StdMat2 *)pMaxMaterial; } else if(pMaxMaterial->ClassID() == Class_ID(BAKE_SHELL_CLASS_ID, 0)) { pMaxStandardMtl = (StdMat2 *)pMaxMaterial->GetSubMtl(0); pMaxBakedMtl = (StdMat2 *)pMaxMaterial->GetSubMtl(1); } if(pMaxStandardMtl) { // Standard material fAlpha = pMaxStandardMtl->GetOpacity(0); Shader* pMaxShader = pMaxStandardMtl->GetShader(); CVector4 v4Specular = ColorToVector4(pMaxStandardMtl->GetSpecular(0), 0.0f) * pMaxShader->GetSpecularLevel(0, 0); pShaderStd->SetAmbient (ColorToVector4(pMaxStandardMtl->GetAmbient(0), 0.0f)); pShaderStd->SetDiffuse (ColorToVector4(pMaxStandardMtl->GetDiffuse(0), fAlpha)); pShaderStd->SetSpecular (v4Specular); pShaderStd->SetShininess(pMaxShader->GetGlossiness(0, 0) * 128.0f); if(pMaxStandardMtl->GetTwoSided() == TRUE) { pShaderStd->SetTwoSided(true); } // Need to cast to StdMat2 in order to get access to IsFaceted(). // ¿Is StdMat2 always the interface for standard materials? if(((StdMat2*)pMaxStandardMtl)->IsFaceted()) { pShaderStd->SetFaceted(true); } if(pMaxStandardMtl->GetWire() == TRUE) { pShaderStd->SetPostWire(true); pShaderStd->SetWireLineThickness(pMaxStandardMtl->GetWireSize(0)); } } else { // Material != Standard fAlpha = 1.0f; // pMaxMaterial->GetXParency(); pShaderStd->SetAmbient (ColorToVector4(pMaxMaterial->GetAmbient(), 0.0f)); pShaderStd->SetDiffuse (ColorToVector4(pMaxMaterial->GetDiffuse(), fAlpha)); pShaderStd->SetSpecular (CVector4(0.0f, 0.0f, 0.0f, 0.0f)); pShaderStd->SetShininess(0.0f); } // Layers if(!pMaxStandardMtl) { m_vecShaders.push_back(pShaderStd); continue; } bool bDiffuseMap32Bits = false; StdMat2 *pStandardMtl; for(int i = 0; i < 3; i++) { int nMap; pStandardMtl = pMaxStandardMtl; // 0 = diffuse, 1 == bump, 2 = lightmap (self illumination slot) or envmap (reflection slot) if(i == 0) { nMap = ID_DI; } else if(i == 1) { nMap = ID_BU; // If its a baked material, get the bump map from there if(pMaxBakedMtl) { pStandardMtl = pMaxBakedMtl; } } else if(i == 2) { bool bBaked = false; // If its a baked material, get the map2 (lightmap) from there if(pMaxBakedMtl) { if(pMaxBakedMtl->GetMapState(ID_SI) == MAXMAPSTATE_ENABLED) { bBaked = true; nMap = ID_SI; pStandardMtl = pMaxBakedMtl; } } if(!bBaked) { if(pStandardMtl->GetMapState(ID_SI) == MAXMAPSTATE_ENABLED) { nMap = ID_SI; } else { nMap = ID_RL; } } } // Check validity if(pStandardMtl->GetMapState(nMap) != MAXMAPSTATE_ENABLED) { if(i == 0) { LOG.Write("\n No diffuse. Skipping."); break; } continue; } Texmap* pMaxTexmap = pStandardMtl->GetSubTexmap(nMap); if(!pMaxTexmap) { if(i == 0) { LOG.Write("\n No diffuse. Skipping."); break; } continue; } // Get texmaps std::vector<std::string> vecTextures, vecPaths; CShaderStandard::SLayerInfo layerInfo; CShaderStandard::SBitmapInfo bitmapInfo; if(pMaxTexmap->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) { BitmapTex* pMaxBitmapTex = (BitmapTex*)pMaxTexmap; Bitmap* pMaxBitmap = pMaxBitmapTex->GetBitmap(SECONDS_TO_TICKS(m_fStartTime)); StdUVGen* pMaxUVGen = pMaxBitmapTex->GetUVGen(); if(!pMaxBitmap) { if(i == 0) { LOG.Write("\n Invalid diffuse. Skipping."); break; } continue; } assert(pMaxUVGen); BitmapInfo bi = pMaxBitmap->Storage()->bi; // bi.Name() returns the full path // bi.Filename() returns just the filename vecTextures.push_back(bi.Filename()); vecPaths. push_back(bi.Name()); LOG.Write("\n Bitmap %s", vecTextures[0].data()); // Check if diffuse texture has alpha channel if(i == 0) { CBitmap bitmap; CInputFile bitmapFile; if(!bitmapFile.Open(bi.Name(), false)) { CLogger::NotifyWindow("WARNING - CStravaganzaMaxTools::BuildShaders():\nUnable to load file %s", bi.Name()); } else { if(!bitmap.Load(&bitmapFile, GetFileExt(bi.Name()))) { CLogger::NotifyWindow("WARNING - CStravaganzaMaxTools::BuildShaders():\nUnable to load bitmap %s", bi.Name()); } else { if(bitmap.GetBpp() == 32) { bDiffuseMap32Bits = true; LOG.Write(" (with alpha channel)"); } bitmap.Free(); } bitmapFile.Close(); } } // Ok, copy properties layerInfo.texInfo.bLoop = false; layerInfo.texInfo.eTextureType = UtilGL::Texturing::CTexture::TEXTURE2D; bitmapInfo.strFile = m_bPreview ? bi.Name() : bi.Filename(); bitmapInfo.bTile = ((pMaxUVGen->GetTextureTiling() & (U_WRAP | V_WRAP)) == (U_WRAP | V_WRAP)) ? true : false; bitmapInfo.fSeconds = 0.0f; bitmapInfo.bForceFiltering = false; bitmapInfo.eFilter = UtilGL::Texturing::FILTER_TRILINEAR; // won't be used (forcefiltering = false) layerInfo.texInfo.m_vecBitmaps.push_back(bitmapInfo); layerInfo.eTexEnv = nMap == ID_RL ? CShaderStandard::TEXENV_ADD : CShaderStandard::TEXENV_MODULATE; layerInfo.eUVGen = pMaxUVGen->GetCoordMapping(0) == UVMAP_SPHERE_ENV ? CShaderStandard::UVGEN_ENVMAPPING : CShaderStandard::UVGEN_EXPLICITMAPPING; layerInfo.uMapChannel = pMaxUVGen->GetMapChannel(); layerInfo.v3ScrollSpeed = CVector3(0.0f, 0.0f, 0.0f); layerInfo.v3RotationSpeed = CVector3(0.0f, 0.0f, 0.0f); layerInfo.v3ScrollOffset = CVector3(pMaxUVGen->GetUOffs(0), pMaxUVGen->GetVOffs(0), 0.0f); layerInfo.v3RotationOffset = CVector3(pMaxUVGen->GetUAng(0), pMaxUVGen->GetVAng(0), pMaxUVGen->GetWAng(0)); } else if(pMaxTexmap->ClassID() == Class_ID(ACUBIC_CLASS_ID, 0)) { ACubic* pMaxCubic = (ACubic*)pMaxTexmap; IParamBlock2* pBlock = pMaxCubic->pblock; Interval validRange = m_pMaxInterface->GetAnimRange(); for(int nFace = 0; nFace < 6; nFace++) { int nMaxFace; switch(nFace) { case 0: nMaxFace = 3; break; case 1: nMaxFace = 2; break; case 2: nMaxFace = 1; break; case 3: nMaxFace = 0; break; case 4: nMaxFace = 5; break; case 5: nMaxFace = 4; break; } TCHAR *name; pBlock->GetValue(acubic_bitmap_names, TICKS_TO_SECONDS(m_fStartTime), name, validRange, nMaxFace); vecPaths.push_back(name); CStr path, file, ext; SplitFilename(CStr(name), &path, &file, &ext); std::string strFile = std::string(file.data()) + ext.data(); vecTextures.push_back(strFile); bitmapInfo.strFile = m_bPreview ? name : strFile; bitmapInfo.bTile = false; bitmapInfo.fSeconds = 0.0f; bitmapInfo.bForceFiltering = false; bitmapInfo.eFilter = UtilGL::Texturing::FILTER_TRILINEAR; layerInfo.texInfo.m_vecBitmaps.push_back(bitmapInfo); } layerInfo.texInfo.bLoop = false; layerInfo.texInfo.eTextureType = UtilGL::Texturing::CTexture::TEXTURECUBEMAP; layerInfo.eTexEnv = nMap == ID_RL ? CShaderStandard::TEXENV_ADD : CShaderStandard::TEXENV_MODULATE; layerInfo.eUVGen = CShaderStandard::UVGEN_ENVMAPPING; layerInfo.uMapChannel = 0; layerInfo.v3ScrollSpeed = CVector3(0.0f, 0.0f, 0.0f); layerInfo.v3RotationSpeed = CVector3(0.0f, 0.0f, 0.0f); layerInfo.v3ScrollOffset = CVector3(0.0f, 0.0f, 0.0f); layerInfo.v3RotationOffset = CVector3(0.0f, 0.0f, 0.0f); } else { if(i == 0) { LOG.Write("\n No diffuse. Skipping."); break; } continue; } if(!m_bPreview && m_bCopyTextures && m_strTexturePath != "") { for(int nTex = 0; nTex != vecTextures.size(); nTex++) { // Copy textures into the specified folder std::string strDestPath = m_strTexturePath; if(strDestPath[strDestPath.length() - 1] != '\\') { strDestPath.append("\\", 1); } strDestPath.append(vecTextures[nTex]); if(!CopyFile(vecPaths[nTex].data(), strDestPath.data(), FALSE)) { CLogger::NotifyWindow("Unable to copy %s to\n%s", vecPaths[i], strDestPath.data()); } } } if(layerInfo.eUVGen == CShaderStandard::UVGEN_ENVMAPPING && i == 1) { CLogger::NotifyWindow("%s : Bump with spheremapping not supported", pShaderStd->GetName().data()); } else { // Add layer switch(i) { case 0: pShaderStd->SetLayer(CShaderStandard::LAYER_DIFF, layerInfo); break; case 1: pShaderStd->SetLayer(CShaderStandard::LAYER_BUMP, layerInfo); break; case 2: pShaderStd->SetLayer(CShaderStandard::LAYER_MAP2, layerInfo); break; } } } // ¿Do we need blending? if(ARE_EQUAL(fAlpha, 1.0f) && !bDiffuseMap32Bits) { pShaderStd->SetBlendSrcFactor(UtilGL::States::BLEND_ONE); pShaderStd->SetBlendDstFactor(UtilGL::States::BLEND_ZERO); } else { pShaderStd->SetBlendSrcFactor(UtilGL::States::BLEND_SRCALPHA); pShaderStd->SetBlendDstFactor(UtilGL::States::BLEND_INVSRCALPHA); } // Add shader m_vecShaders.push_back(pShaderStd); } return true; }
AWDTexture * AWDExporter::ExportTexture(AWD *awd, awd_ncache *ncache,Texmap* tex, Class_ID cid, int subNo, AWDMaterial * mat ) { AWDTexture *awd_tex; const char* name; int name_len; bool hasAlpha = false; MSTR path; awd_uint8 * buf; int buf_len; if (!tex) return NULL; if (tex->ClassID() != Class_ID(BMTEX_CLASS_ID, 0x00) ) return NULL; // texture already exist in cache awd_tex = (AWDTexture *)awd_ncache_get( ncache, tex ); if( awd_tex ) return awd_tex; BitmapTex *bmptex = (BitmapTex*)tex; MaxSDK::AssetManagement::AssetUser asset = bmptex->GetMap(); hasAlpha = bmptex->GetBitmap( GetStaticFrame() )->HasAlpha(); if( !asset.GetFullFilePath(path) ) { fprintf( logfile, " export !asset.GetFullFilePath(path) : %i \n", asset.GetType() ); fflush( logfile ); //return NULL; } fprintf( logfile, " export : %s \n", path ); fflush( logfile ); AWD_tex_type textype = EXTERNAL; if( GetIncludeMaps() && asset.GetType() == MaxSDK::AssetManagement::kBitmapAsset ) { const char * dot; dot = strrchr(path,'.'); if( !strcmp(dot, ".jpg")|| !strcmp(dot, ".JPG")|| !strcmp(dot, ".jpeg")|| !strcmp(dot, ".JPEG") ) { textype = EMBEDDED_JPEG; } else if ( !strcmp(dot, ".png")|| !strcmp(dot, ".PNG") ) { textype = EMBEDDED_PNG; } if( textype == 0 ) { fprintf( logfile, " export texture : %s \n", path ); fflush( logfile ); // try to extract data Bitmap *bmp = bmptex->GetBitmap( GetStaticFrame() ); BitmapInfo bi; MaxSDK::Util::Path *temppath; bi.SetWidth( bmp->Width() ); bi.SetHeight( bmp->Height() ); if( hasAlpha ) { bi.SetType( BMM_TRUE_32 ); bi.SetFlags( MAP_HAS_ALPHA ); path = "C:\\Users\\lepersp\\Desktop\\temp\\awdexporttempjpg.png"; textype = EMBEDDED_PNG; } else { bi.SetType( BMM_TRUE_24 ); path = "C:\\Users\\lepersp\\Desktop\\temp\\awdexporttempjpg.jpg"; textype = EMBEDDED_JPEG; } temppath = new MaxSDK::Util::Path( path ); bi.SetPath( *temppath ); bmp->OpenOutput( & bi ); bmp->Write( & bi ); bmp->Close(& bi); } if( path != NULL ) { size_t result; int fd; errno_t err = _sopen_s( &fd, path, _O_RDONLY|_O_BINARY, _SH_DENYNO, _S_IREAD ); if( err == 0 ) { struct stat *s; s = (struct stat *)malloc(sizeof(struct stat)); fstat(fd, s); buf_len = s->st_size; buf = (awd_uint8 *) malloc (buf_len * sizeof( awd_uint8 ) ); lseek(fd, 0, SEEK_SET); result = read(fd, buf, buf_len); if (result != buf_len) { textype = EXTERNAL; } _close( fd ); } else { textype = EXTERNAL; } } } name = tex->GetName(); name_len = strlen( name ); char* namecpy = (char*) malloc( name_len*sizeof( char ) ) ; strcpy( namecpy, name ); awd_tex = new AWDTexture( textype, namecpy, name_len ); if( textype != 0 ) { awd_tex->set_embed_data(buf, buf_len); } char * pathcpy = (char *) malloc( (path.length()+1) * sizeof( char ) ); strcpy( pathcpy, path.data() ); awd_tex->set_url( pathcpy, strlen( pathcpy ) ); awd->add_texture( awd_tex ); awd_ncache_add( ncache, tex, awd_tex ); if( subNo == ID_DI ) { mat->set_texture( awd_tex ); mat->alpha_blending = hasAlpha; } return awd_tex; }