void ColladaSerializer::ColladaExporter::ColladaMaterials::ColladaEffects::write(const IfcGeom::Material& material) { openEffect(collada_id(material.name()) + "-fx"); COLLADASW::EffectProfile effect(mSW); effect.setShaderType(COLLADASW::EffectProfile::LAMBERT); if (material.hasDiffuse()) { const double* diffuse = material.diffuse(); effect.setDiffuse(COLLADASW::ColorOrTexture(COLLADASW::Color(diffuse[0],diffuse[1],diffuse[2]))); } if (material.hasSpecular()) { const double* specular = material.specular(); effect.setSpecular(COLLADASW::ColorOrTexture(COLLADASW::Color(specular[0],specular[1],specular[2]))); } if (material.hasSpecularity()) { effect.setShininess(material.specularity()); } if (material.hasTransparency()) { const double transparency = material.transparency(); if (transparency > 0) { // The default opacity mode for Collada is A_ONE, which apparently indicates a // transparency value of 1 to be fully opaque. Hence transparency is inverted. effect.setTransparency(1.0 - transparency); } } addEffectProfile(effect); closeEffect(); }
void EffectsExporter::exportEffects(Scene *sce) { this->scene = sce; if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) { if (hasEffects(sce)) { MaterialFunctor mf; openLibrary(); mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set); closeLibrary(); } } else { std::set<Object *> uv_textured_obs = bc_getUVTexturedObjects(sce, !this->export_settings->active_uv_only); std::set<Image *> uv_images = bc_getUVImages(sce, !this->export_settings->active_uv_only); if (uv_images.size() > 0) { openLibrary(); std::set<Image *>::iterator uv_images_iter; for (uv_images_iter = uv_images.begin(); uv_images_iter != uv_images.end(); uv_images_iter++) { Image *ima = *uv_images_iter; std::string key(id_name(ima)); key = translate_id(key); COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D, key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX, key + COLLADASW::Sampler::SURFACE_SID_SUFFIX); sampler.setImageId(key); openEffect(key + "-effect"); COLLADASW::EffectProfile ep(mSW); ep.setProfileType(COLLADASW::EffectProfile::COMMON); ep.setShaderType(COLLADASW::EffectProfile::PHONG); ep.setDiffuse(createTexture(ima, key, &sampler), false, "diffuse"); COLLADASW::ColorOrTexture cot = getcol(0, 0, 0, 1.0f); ep.setSpecular(cot, false, "specular"); ep.openProfile(); ep.addProfileElements(); ep.addExtraTechniques(mSW); ep.closeProfile(); closeEffect(); } closeLibrary(); } } }
void EffectsExporter::operator()(Material *ma, Object *ob) { // create a list of indices to textures of type TEX_IMAGE std::vector<int> tex_indices; if (this->export_settings->include_material_textures) createTextureIndices(ma, tex_indices); openEffect(translate_id(id_name(ma)) + "-effect"); COLLADASW::EffectProfile ep(mSW); ep.setProfileType(COLLADASW::EffectProfile::COMMON); ep.openProfile(); // set shader type - one of three blinn, phong or lambert if (ma->spec > 0.0f) { if (ma->spec_shader == MA_SPEC_BLINN) { writeBlinn(ep, ma); } else { // \todo figure out handling of all spec+diff shader combos blender has, for now write phong // for now set phong in case spec shader is not blinn writePhong(ep, ma); } } else { if (ma->diff_shader == MA_DIFF_LAMBERT) { writeLambert(ep, ma); } else { // \todo figure out handling of all spec+diff shader combos blender has, for now write phong writePhong(ep, ma); } } // index of refraction if (ma->mode & MA_RAYTRANSP) { ep.setIndexOfRefraction(ma->ang, false, "index_of_refraction"); } else { ep.setIndexOfRefraction(1.0f, false, "index_of_refraction"); } COLLADASW::ColorOrTexture cot; // transparency if (ma->mode & MA_TRANSP) { // Tod: because we are in A_ONE mode transparency is calculated like this: ep.setTransparency(ma->alpha, false, "transparency"); // cot = getcol(1.0f, 1.0f, 1.0f, 1.0f); // ep.setTransparent(cot); } // emission cot = getcol(ma->emit, ma->emit, ma->emit, 1.0f); ep.setEmission(cot, false, "emission"); // diffuse multiplied by diffuse intensity cot = getcol(ma->r * ma->ref, ma->g * ma->ref, ma->b * ma->ref, 1.0f); ep.setDiffuse(cot, false, "diffuse"); // ambient /* ma->ambX is calculated only on render, so lets do it here manually and not rely on ma->ambX. */ if (this->scene->world) cot = getcol(this->scene->world->ambr * ma->amb, this->scene->world->ambg * ma->amb, this->scene->world->ambb * ma->amb, 1.0f); else cot = getcol(ma->amb, ma->amb, ma->amb, 1.0f); ep.setAmbient(cot, false, "ambient"); // reflective, reflectivity if (ma->mode & MA_RAYMIRROR) { cot = getcol(ma->mirr, ma->mirg, ma->mirb, 1.0f); ep.setReflective(cot); ep.setReflectivity(ma->ray_mirror); } // else { // cot = getcol(ma->specr, ma->specg, ma->specb, 1.0f); // ep.setReflective(cot); // ep.setReflectivity(ma->spec); // } // specular if (ep.getShaderType() != COLLADASW::EffectProfile::LAMBERT) { cot = getcol(ma->specr * ma->spec, ma->specg * ma->spec, ma->specb * ma->spec, 1.0f); ep.setSpecular(cot, false, "specular"); } // XXX make this more readable if possible // create <sampler> and <surface> for each image COLLADASW::Sampler samplers[MAX_MTEX]; //COLLADASW::Surface surfaces[MAX_MTEX]; //void *samp_surf[MAX_MTEX][2]; void *samp_surf[MAX_MTEX][1]; // image to index to samp_surf map // samp_surf[index] stores 2 pointers, sampler and surface std::map<std::string, int> im_samp_map; unsigned int a, b; for (a = 0, b = 0; a < tex_indices.size(); a++) { MTex *t = ma->mtex[tex_indices[a]]; Image *ima = t->tex->ima; // Image not set for texture if (!ima) continue; std::string key(id_name(ima)); key = translate_id(key); // create only one <sampler>/<surface> pair for each unique image if (im_samp_map.find(key) == im_samp_map.end()) { // //<newparam> <surface> <init_from> // COLLADASW::Surface surface(COLLADASW::Surface::SURFACE_TYPE_2D, // key + COLLADASW::Surface::SURFACE_SID_SUFFIX); // COLLADASW::SurfaceInitOption sio(COLLADASW::SurfaceInitOption::INIT_FROM); // sio.setImageReference(key); // surface.setInitOption(sio); // COLLADASW::NewParamSurface surface(mSW); // surface->setParamType(COLLADASW::CSW_SURFACE_TYPE_2D); //<newparam> <sampler> <source> COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D, key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX, key + COLLADASW::Sampler::SURFACE_SID_SUFFIX); sampler.setImageId(key); // copy values to arrays since they will live longer samplers[a] = sampler; //surfaces[a] = surface; // store pointers so they can be used later when we create <texture>s samp_surf[b][0] = &samplers[a]; //samp_surf[b][1] = &surfaces[a]; im_samp_map[key] = b; b++; } } std::set<Image *> uv_textures; if (ob->type == OB_MESH && ob->totcol && this->export_settings->include_uv_textures) { bool active_uv_only = this->export_settings->active_uv_only; Mesh *me = (Mesh *) ob->data; int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY); BKE_mesh_tessface_ensure(me); for (int i = 0; i < me->pdata.totlayer; i++) { if (!active_uv_only || active_uv_layer == i) { if (me->pdata.layers[i].type == CD_MTEXPOLY) { MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data; MFace *mface = me->mface; for (int j = 0; j < me->totpoly; j++, mface++, txface++) { Material *mat = give_current_material(ob, mface->mat_nr + 1); if (mat != ma) continue; Image *ima = txface->tpage; if (ima == NULL) continue; bool not_in_list = uv_textures.find(ima)==uv_textures.end(); if (not_in_list) { std::string name = id_name(ima); std::string key(name); key = translate_id(key); // create only one <sampler>/<surface> pair for each unique image if (im_samp_map.find(key) == im_samp_map.end()) { //<newparam> <sampler> <source> COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D, key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX, key + COLLADASW::Sampler::SURFACE_SID_SUFFIX); sampler.setImageId(key); samplers[a] = sampler; samp_surf[b][0] = &samplers[a]; im_samp_map[key] = b; b++; a++; uv_textures.insert(ima); } } } } } } } // used as fallback when MTex->uvname is "" (this is pretty common) // it is indeed the correct value to use in that case std::string active_uv(getActiveUVLayerName(ob)); // write textures // XXX very slow for (a = 0; a < tex_indices.size(); a++) { MTex *t = ma->mtex[tex_indices[a]]; Image *ima = t->tex->ima; std::string key(id_name(ima)); key = translate_id(key); int i = im_samp_map[key]; std::string uvname = strlen(t->uvname) ? t->uvname : active_uv; COLLADASW::Sampler *sampler = (COLLADASW::Sampler *)samp_surf[i][0]; writeTextures(ep, key, sampler, t, ima, uvname); } std::set<Image *>::iterator uv_t_iter; for (uv_t_iter = uv_textures.begin(); uv_t_iter != uv_textures.end(); uv_t_iter++ ) { Image *ima = *uv_t_iter; std::string key(id_name(ima)); key = translate_id(key); int i = im_samp_map[key]; COLLADASW::Sampler *sampler = (COLLADASW::Sampler *)samp_surf[i][0]; ep.setDiffuse(createTexture(ima, active_uv, sampler), false, "diffuse"); } // performs the actual writing ep.addProfileElements(); bool twoSided = false; if (ob->type == OB_MESH && ob->data) { Mesh *me = (Mesh *)ob->data; if (me->flag & ME_TWOSIDED) twoSided = true; } if (twoSided) ep.addExtraTechniqueParameter("GOOGLEEARTH", "double_sided", 1); ep.addExtraTechniques(mSW); ep.closeProfile(); if (twoSided) mSW->appendTextBlock("<extra><technique profile=\"MAX3D\"><double_sided>1</double_sided></technique></extra>"); closeEffect(); }