Collada: added new functions for improved material exporter (not used yet)

This commit is contained in:
Gaia Clary 2017-06-24 21:36:03 +02:00
parent ce531ed1a1
commit 0d2b1da3a6
6 changed files with 362 additions and 9 deletions

View File

@ -52,6 +52,7 @@ extern "C" {
#include "collada_internal.h"
#include "collada_utils.h"
// TODO: optimize UV sets by making indexed list with duplicates removed
GeometryExporter::GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryGeometries(sw), export_settings(export_settings)
{
@ -420,6 +421,165 @@ void GeometryExporter::createPolylist(short material_index,
polylist.finish();
}
void GeometryExporter::createPolylists(std::set<Image *> uv_images,
bool has_uvs,
bool has_color,
Object *ob,
Mesh *me,
std::string& geom_id,
std::vector<BCPolygonNormalsIndices>& norind)
{
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;
createPolylist(ima, has_uvs,
has_color,
ob,
me,
geom_id,
norind);
}
}
// Export Meshes with UV Textures (export as materials, see effectExporter and MaterialExporter)
// Important: Image *ima must point to an Image
void GeometryExporter::createPolylist(Image *ima,
bool has_uvs,
bool has_color,
Object *ob,
Mesh *me,
std::string& geom_id,
std::vector<BCPolygonNormalsIndices>& norind)
{
std::string imageid(id_name(ima));
MPoly *mpolys = me->mpoly;
MLoop *mloops = me->mloop;
MTexPoly *mtpolys = me->mtpoly;
int totpolys = me->totpoly;
// <vcount>
int i;
int faces_in_polylist = 0;
std::vector<unsigned long> vcount_list;
// count faces with this material
for (i = 0; i < totpolys; i++) {
MTexPoly *tp = &mtpolys[i];
MPoly *p = &mpolys[i];
std::string tpageid(id_name(tp->tpage));
if (tpageid == imageid) {
faces_in_polylist++;
vcount_list.push_back(p->totloop);
}
}
// no faces using this material
if (faces_in_polylist == 0) {
fprintf(stderr, "%s: Image %s is not used.\n", id_name(ob).c_str(), imageid);
return;
}
COLLADASW::Polylist polylist(mSW);
// sets count attribute in <polylist>
polylist.setCount(faces_in_polylist);
// sets material name
std::string material_id = get_material_id_from_id(imageid);
std::ostringstream ostr;
ostr << translate_id(material_id);
polylist.setMaterial(ostr.str());
COLLADASW::InputList &til = polylist.getInputList();
// creates <input> in <polylist> for vertices
COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0);
// creates <input> in <polylist> for normals
COLLADASW::Input input2(COLLADASW::InputSemantic::NORMAL, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL), 1);
til.push_back(input1);
til.push_back(input2);
// if mesh has uv coords writes <input> for TEXCOORD
int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
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);
/* 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(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);
}
}
int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
if (totlayer_mcol > 0) {
int map_index = 0;
for (int a = 0; a < totlayer_mcol; a++) {
char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a);
COLLADASW::Input input4(COLLADASW::InputSemantic::COLOR,
makeUrl(makeVertexColorSourceId(geom_id, layer_name)),
(has_uvs) ? 3 : 2, // all color layers have same index order
map_index // set number equals color map index
);
til.push_back(input4);
map_index++;
}
}
// sets <vcount>
polylist.setVCountList(vcount_list);
// performs the actual writing
polylist.prepareToAppendValues();
// <p>
int texindex = 0;
for (i = 0; i < totpolys; i++) {
MTexPoly *tp = &mtpolys[i];
MPoly *p = &mpolys[i];
int loop_count = p->totloop;
std::string tpageid(id_name(tp->tpage));
if (tpageid == imageid) {
MLoop *l = &mloops[p->loopstart];
BCPolygonNormalsIndices normal_indices = norind[i];
for (int j = 0; j < loop_count; j++) {
polylist.appendValues(l[j].v);
polylist.appendValues(normal_indices[j]);
if (has_uvs)
polylist.appendValues(texindex + j);
if (has_color)
polylist.appendValues(texindex + j);
}
}
texindex += loop_count;
}
polylist.finish();
}
// creates <source> for positions
void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me)

View File

@ -85,15 +85,33 @@ public:
Mesh *me,
std::string& geom_id);
// powerful because it handles both cases when there is material and when there's not
// Create polylists for meshes with Materials
void createPolylist(short material_index,
bool has_uvs,
bool has_color,
Object *ob,
Mesh *me,
std::string& geom_id,
std::vector<BCPolygonNormalsIndices>& norind);
bool has_uvs,
bool has_color,
Object *ob,
Mesh *me,
std::string& geom_id,
std::vector<BCPolygonNormalsIndices>& norind);
// Create polylists for meshes with UV Textures
void createPolylists(std::set<Image *> uv_images,
bool has_uvs,
bool has_color,
Object *ob,
Mesh *me,
std::string& geom_id,
std::vector<BCPolygonNormalsIndices>& norind);
// Create polylists for meshes with UV Textures
void createPolylist(Image *ima,
bool has_uvs,
bool has_color,
Object *ob,
Mesh *me,
std::string& geom_id,
std::vector<BCPolygonNormalsIndices>& norind);
// creates <source> for positions
void createVertsSource(std::string geom_id, Mesh *me);

View File

@ -344,7 +344,13 @@ std::string get_camera_id(Object *ob)
std::string get_material_id(Material *mat)
{
return translate_id(id_name(mat)) + "-material";
std::string id = id_name(mat);
return get_material_id_from_id(id);
}
std::string get_material_id_from_id(std::string id)
{
return translate_id(id) + "-material";
}
std::string get_morph_id(Object *ob)

View File

@ -103,6 +103,7 @@ extern std::string get_joint_sid(Bone *bone, Object *ob_arm);
extern std::string get_camera_id(Object *ob);
extern std::string get_material_id(Material *mat);
extern std::string get_material_id_from_id(std::string id);
extern std::string get_morph_id(Object *ob);

View File

@ -32,6 +32,8 @@
#include "COLLADAFWMeshPrimitive.h"
#include "COLLADAFWMeshVertexData.h"
#include <set>
extern "C" {
#include "DNA_modifier_types.h"
#include "DNA_customdata_types.h"
@ -831,4 +833,160 @@ void bc_sanitize_mat(float mat[4][4], int precision)
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
mat[i][j] = double_round(mat[i][j], precision);
}
/*
* Returns name of Active UV Layer or empty String if no active UV Layer defined.
* Assuming the Object is of type MESH
*/
std::string bc_get_active_uvlayer_name(Object *ob)
{
Mesh *me = (Mesh *)ob->data;
return bc_get_active_uvlayer_name(me);
}
/*
* Returns name of Active UV Layer or empty String if no active UV Layer defined
*/
std::string bc_get_active_uvlayer_name(Mesh *me)
{
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 "";
}
/*
* Returns UV Layer name or empty string if layer index is out of range
*/
std::string bc_get_uvlayer_name(Mesh *me, int layer)
{
int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
if (num_layers && layer < num_layers) {
return std::string(bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, layer));
}
return "";
}
/**********************************************************************
*
* Return the list of Mesh objects with assigned UVtextures and Images
* Note: We need to create artificaial materials for each of them
*
***********************************************************************/
std::set<Object *> bc_getUVTexturedObjects(Scene *sce, bool all_uv_layers)
{
std::set <Object *> UVObjects;
Base *base = (Base *)sce->base.first;
while (base) {
Object *ob = base->object;
bool has_uvimage = false;
if (ob->type == OB_MESH) {
Mesh *me = (Mesh *)ob->data;
int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
if (all_uv_layers || active_uv_layer == i)
{
if (me->pdata.layers[i].type == CD_MTEXPOLY) {
MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
MPoly *mpoly = me->mpoly;
for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
Image *ima = txface->tpage;
if (ima != NULL) {
has_uvimage = true;
break;
}
}
}
}
}
if (has_uvimage) {
UVObjects.insert(ob);
}
}
base = base->next;
}
return UVObjects;
}
/**********************************************************************
*
* Return the list of UV Texture images from all exported Mesh Items
* Note: We need to create one artificial material for each Image.
*
***********************************************************************/
std::set<Image *> bc_getUVImages(Scene *sce, bool all_uv_layers)
{
std::set <Image *> UVImages;
Base *base = (Base *)sce->base.first;
while (base) {
Object *ob = base->object;
bool has_uvimage = false;
if (ob->type == OB_MESH) {
Mesh *me = (Mesh *)ob->data;
int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
if (all_uv_layers || active_uv_layer == i)
{
if (me->pdata.layers[i].type == CD_MTEXPOLY) {
MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
MPoly *mpoly = me->mpoly;
for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
Image *ima = txface->tpage;
if (ima != NULL) {
if (UVImages.find(ima) == UVImages.end())
UVImages.insert(ima);
}
}
}
}
}
}
base = base->next;
}
return UVImages;
}
/**********************************************************************
*
* Return the list of UV Texture images for the given Object
* Note: We need to create one artificial material for each Image.
*
***********************************************************************/
std::set<Image *> bc_getUVImages(Object *ob, bool all_uv_layers)
{
std::set <Image *> UVImages;
bool has_uvimage = false;
if (ob->type == OB_MESH) {
Mesh *me = (Mesh *)ob->data;
int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
if (all_uv_layers || active_uv_layer == i)
{
if (me->pdata.layers[i].type == CD_MTEXPOLY) {
MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
MPoly *mpoly = me->mpoly;
for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
Image *ima = txface->tpage;
if (ima != NULL) {
if (UVImages.find(ima) == UVImages.end())
UVImages.insert(ima);
}
}
}
}
}
}
return UVImages;
}

View File

@ -34,6 +34,7 @@
#include <vector>
#include <map>
#include <set>
#include <algorithm>
extern "C" {
@ -80,6 +81,7 @@ extern void bc_set_mark(Object *ob);
extern char *bc_CustomData_get_layer_name(const CustomData *data, int type, int n);
extern char *bc_CustomData_get_active_layer_name(const CustomData *data, int type);
extern char *bc_CustomData_get_layer_name(const CustomData *data, int layer_index, int type);
extern void bc_bubble_sort_by_Object_name(LinkNode *export_set);
extern bool bc_is_root_bone(Bone *aBone, bool deform_bones_only);
@ -109,6 +111,14 @@ extern bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4])
extern void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float world[4][4], bool use_local_space);
extern std::string bc_get_active_uvlayer_name(Object *ob);
extern std::string bc_get_active_uvlayer_name(Mesh *me);
extern std::string bc_get_uvlayer_name(Mesh *me, int layer);
extern std::set<Image *> bc_getUVImages(Scene *sce, bool all_uv_layers);
extern std::set<Image *> bc_getUVImages(Object *ob, bool all_uv_layers);
extern std::set<Object *> bc_getUVTexturedObjects(Scene *sce, bool all_uv_layers);
class BCPolygonNormalsIndices
{
std::vector<unsigned int> normal_indices;