collada: export UV Textures as materials. Note: the reimport of the exported collada files will have materials assigned instead of UV Face Textures! This is expected behavior

This commit is contained in:
Gaia Clary
2017-06-24 22:16:32 +02:00
parent a2a301bdb9
commit ddabe465b5
8 changed files with 158 additions and 57 deletions

View File

@@ -138,7 +138,8 @@ extern bool bc_has_object_type(LinkNode *export_set, short obtype);
char *bc_CustomData_get_layer_name(const struct CustomData *data, int type, int n)
{
int layer_index = CustomData_get_layer_index(data, type);
if (layer_index < 0) return NULL;
if (layer_index < 0)
return NULL;
return data->layers[layer_index + n].name;
}
@@ -147,9 +148,10 @@ char *bc_CustomData_get_active_layer_name(const CustomData *data, int type)
{
/* get the layer index of the active layer of type */
int layer_index = CustomData_get_active_layer_index(data, type);
if (layer_index < 0) return NULL;
if (layer_index < 1)
return NULL;
return data->layers[layer_index].name;
return bc_CustomData_get_layer_name(data, type, layer_index-1);
}
DocumentExporter::DocumentExporter(const ExportSettings *export_settings) : export_settings(export_settings) {

View File

@@ -27,7 +27,6 @@
#include <map>
#include <set>
#include "COLLADASWEffectProfile.h"
#include "COLLADAFWColorOrTexture.h"
@@ -49,21 +48,10 @@ extern "C" {
#include "BKE_material.h"
}
// OB_MESH is assumed
static std::string getActiveUVLayerName(Object *ob)
{
Mesh *me = (Mesh *)ob->data;
int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
if (num_layers)
return std::string(bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE));
return "";
}
EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryEffects(sw), export_settings(export_settings) {
}
bool EffectsExporter::hasEffects(Scene *sce)
{
Base *base = (Base *)sce->base.first;
@@ -86,13 +74,49 @@ bool EffectsExporter::hasEffects(Scene *sce)
void EffectsExporter::exportEffects(Scene *sce)
{
if (hasEffects(sce)) {
this->scene = sce;
openLibrary();
MaterialFunctor mf;
mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set);
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 if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_UV) {
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++) {
closeLibrary();
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();
}
}
}
@@ -172,6 +196,18 @@ void EffectsExporter::writeTextures(COLLADASW::EffectProfile &ep,
}
}
void EffectsExporter::exportUVMats(Object *ob)
{
std::vector<int> tex_indices;
int active_uv_layer = -1;
std::set<Image *> uv_textures;
if (ob->type == OB_MESH && ob->totcol && this->export_settings->export_texture_type == BC_TEXTURE_TYPE_UV) {
bool active_uv_only = this->export_settings->active_uv_only;
Mesh *me = (Mesh *)ob->data;
active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
}
}
void EffectsExporter::operator()(Material *ma, Object *ob)
{
// create a list of indices to textures of type TEX_IMAGE
@@ -365,7 +401,7 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
// 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));
std::string active_uv(bc_get_active_uvlayer_name(ob));
// write textures
// XXX very slow
@@ -385,16 +421,18 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
writeTextures(ep, key, sampler, t, ima, uvname);
}
std::set<Image *>::iterator uv_t_iter;
int idx;
for (idx = 0, uv_t_iter = uv_textures.begin(); uv_t_iter != uv_textures.end(); uv_t_iter++, idx++ ) {
if (active_uv_layer>-1 && idx==active_uv_layer) {
if (active_uv_layer > -1) {
// Export only UV textures assigned to active UV Layer (sounds reasonable, but is that correct?)
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];
ep.setDiffuse(createTexture(ima, active_uv, sampler), false, "diffuse");
ep.setShaderType(COLLADASW::EffectProfile::PHONG);
}
}

View File

@@ -47,6 +47,8 @@ class EffectsExporter: COLLADASW::LibraryEffects
{
public:
EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
void EffectsExporter::exportUVMats(Object *ob);
void exportEffects(Scene *sce);
void operator()(Material *ma, Object *ob);

View File

@@ -135,13 +135,15 @@ void GeometryExporter::operator()(Object *ob)
// Only create Polylists if number of faces > 0
if (me->totface > 0) {
// XXX slow
if (ob->totcol) {
if (ob->totcol && this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
for (int a = 0; a < ob->totcol; a++) {
createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
}
}
else {
createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind);
bool all_uv_layers = !this->export_settings->active_uv_only;
std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind);
}
}
@@ -221,13 +223,15 @@ void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb)
//createLooseEdgeList(ob, me, geom_id, norind);
// XXX slow
if (ob->totcol) {
if (ob->totcol && this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
for (int a = 0; a < ob->totcol; a++) {
createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
}
}
else {
createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind);
bool all_uv_layers = !this->export_settings->active_uv_only;
std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind);
}
closeMesh();
@@ -296,7 +300,8 @@ std::string GeometryExporter::makeVertexColorSourceId(std::string& geom_id, char
return result;
}
// powerful because it handles both cases when there is material and when there's not
// Export meshes with Materials
void GeometryExporter::createPolylist(short material_index,
bool has_uvs,
bool has_color,
@@ -361,13 +366,21 @@ void GeometryExporter::createPolylist(short material_index,
int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE)-1;
for (i = 0; i < num_layers; i++) {
if (!this->export_settings->active_uv_only || i == active_uv_index) {
std::string uv_name(bc_get_uvlayer_name(me, i));
std::string effective_id = geom_id; // (uv_name == "") ? geom_id : uv_name;
std::string layer_id = makeTexcoordSourceId(
effective_id,
i, this->export_settings->active_uv_only);
// char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i);
/* Note: the third parameter denotes the offset of TEXCOORD in polylist elements
For now this is always 2 (This may change sometime/maybe)
*/
COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD,
makeUrl(makeTexcoordSourceId(geom_id, i, this->export_settings->active_uv_only)),
2, // this is only until we have optimized UV sets
(this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set
);
makeUrl(layer_id),
2, // this is only until we have optimized UV sets
(this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set
);
til.push_back(input3);
}
}
@@ -697,7 +710,13 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me)
MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a);
COLLADASW::FloatSourceF source(mSW);
std::string layer_id = makeTexcoordSourceId(geom_id, a, this->export_settings->active_uv_only);
std::string active_uv_name(bc_get_active_uvlayer_name(me));
std::string effective_id = geom_id; // (active_uv_name == "") ? geom_id : active_uv_name;
std::string layer_id = makeTexcoordSourceId(
effective_id,
a,
this->export_settings->active_uv_only );
source.setId(layer_id);
source.setArrayId(layer_id + ARRAY_ID_SUFFIX);

View File

@@ -55,9 +55,9 @@ ImagesExporter::ImagesExporter(COLLADASW::StreamWriter *sw, const ExportSettings
void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
{
std::string name(id_name(image));
std::string translated_name(translate_id(name));
bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_name) == mImages.end();
std::string id(id_name(image));
std::string translated_id(translate_id(id));
bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_id) == mImages.end();
if (not_yet_exported) {
@@ -88,7 +88,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
// make absolute destination path
BLI_strncpy(export_file, name.c_str(), sizeof(export_file));
BLI_strncpy(export_file, id.c_str(), sizeof(export_file));
BKE_image_path_ensure_ext_from_imformat(export_file, &imageFormat);
BLI_join_dirfile(export_path, sizeof(export_path), export_dir, export_file);
@@ -143,10 +143,11 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
}
}
COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_name, translated_name); /* set name also to mNameNC. This helps other viewers import files exported from Blender better */
/* set name also to mNameNC. This helps other viewers import files exported from Blender better */
COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_id, translated_id);
img.add(mSW);
fprintf(stdout, "Collada export: Added image: %s\n", export_file);
mImages.push_back(translated_name);
mImages.push_back(translated_id);
BKE_image_release_ibuf(image, imbuf, NULL);
}
@@ -161,7 +162,7 @@ void ImagesExporter::export_UV_Images()
for (node = this->export_settings->export_set; node; node = node->next) {
Object *ob = (Object *)node->link;
if (ob->type == OB_MESH && ob->totcol) {
if (ob->type == OB_MESH) {
Mesh *me = (Mesh *) ob->data;
BKE_mesh_tessface_ensure(me);
int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
@@ -189,7 +190,13 @@ void ImagesExporter::export_UV_Images()
}
}
/* ============================================================
* Check if there are any images to be exported
* Returns true as soon as an object is detected that
* either has an UV Texture assigned, or has a material
* assigned that uses an Image Texture.
* ============================================================
*/
bool ImagesExporter::hasImages(Scene *sce)
{
LinkNode *node;

View File

@@ -43,14 +43,19 @@ extern "C" {
void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only, BC_export_texture_type export_texture_type)
{
for (int a = 0; a < ob->totcol; a++) {
Material *ma = give_current_material(ob, a + 1);
COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList();
bool all_uv_layers = !active_uv_only;
COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList();
if (ma) {
std::string matid(get_material_id(ma));
matid = translate_id(matid);
if (export_texture_type == BC_TEXTURE_TYPE_UV)
{
std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
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 matid(id_name(ima));
matid = get_material_id_from_id(matid);
std::ostringstream ostr;
ostr << matid;
COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid));
@@ -71,4 +76,32 @@ void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_materia
iml.push_back(im);
}
}
else if (export_texture_type == BC_TEXTURE_TYPE_MAT) {
for (int a = 0; a < ob->totcol; a++) {
Material *ma = give_current_material(ob, a + 1);
if (ma) {
std::string matid(get_material_id(ma));
matid = translate_id(matid);
std::ostringstream ostr;
ostr << matid;
COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid));
// create <bind_vertex_input> for each uv map
Mesh *me = (Mesh *)ob->data;
int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
int map_index = 0;
int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
for (int b = 0; b < totlayer; b++) {
if (!active_uv_only || b == active_uv_index) {
char *name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, b);
im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", map_index++));
}
}
iml.push_back(im);
}
}
}
}

View File

@@ -31,11 +31,12 @@
#include "COLLADASWBindMaterial.h"
#include "DNA_object_types.h"
#include "collada.h"
class InstanceWriter
{
protected:
void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only);
void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only, BC_export_texture_type export_texture_type);
};
#endif

View File

@@ -49,8 +49,7 @@ void MaterialsExporter::exportMaterials(Scene *sce)
closeLibrary();
}
}
#if 0
// Temporary discarded (to keep consistent commits)
else if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_UV)
{
std::set<Image *> uv_images = bc_getUVImages(sce, !this->export_settings->active_uv_only);
@@ -72,7 +71,7 @@ void MaterialsExporter::exportMaterials(Scene *sce)
closeLibrary();
}
}
#endif
}
bool MaterialsExporter::hasMaterials(Scene *sce)