Changed textures import. Although code is still difficult to understand.

This commit is contained in:
Chingiz Dyussenov
2009-07-27 17:43:13 +00:00
parent 6a4d9cae72
commit a5d8e6e5cd

View File

@@ -154,6 +154,8 @@ public:
}
};
typedef std::map<COLLADAFW::TextureMapId, std::vector<MTex*> > TexIndexTextureArrayMap;
class ArmatureImporter
{
private:
@@ -359,11 +361,12 @@ private:
};
typedef std::map<COLLADAFW::MaterialId, std::vector<Primitive> > MaterialIdPrimitiveArrayMap;
std::map<COLLADAFW::UniqueId, MaterialIdPrimitiveArrayMap> geom_uid_mat_mapping_map; // crazy name!
/*
// maps for assigning textures to uv layers
//std::map<COLLADAFW::TextureMapId, char*> set_layername_map;
std::map<COLLADAFW::TextureMapId, std::vector<MTex*> > index_mtex_map;
typedef std::map<COLLADAFW::TextureMapId, std::vector<MTex*> > TexIndexTextureArrayMap;
std::map<Material*, TexIndexTextureArrayMap> material_texture_mapping_map;
*/
class UVDataWrapper
{
COLLADAFW::MeshVertexData *mVData;
@@ -389,6 +392,7 @@ private:
case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT:
{
COLLADAFW::ArrayPrimitiveType<float>* values = mVData->getFloatValues();
if (values->empty()) return;
uv[0] = (*values)[uv_index[0]];
uv[1] = (*values)[uv_index[1]];
@@ -397,7 +401,7 @@ private:
case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
{
COLLADAFW::ArrayPrimitiveType<double>* values = mVData->getDoubleValues();
if (values->empty()) return;
uv[0] = (float)(*values)[uv_index[0]];
uv[1] = (float)(*values)[uv_index[1]];
@@ -413,6 +417,10 @@ private:
mface->v2 = indices[1];
mface->v3 = indices[2];
if (quad) mface->v4 = indices[3];
else mface->v4 = 0;
#ifdef COLLADA_DEBUG
fprintf(stderr, "%u, %u, %u \n", indices[0], indices[1], indices[2]);
#endif
}
// change face indices order so that v4 is not 0
@@ -630,7 +638,7 @@ private:
set_face_indices(mface, indices, false);
indices += 3;
for (k = 0; k < totuvset; k++) {
// get mtface by face index and uv set index
MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, k);
@@ -684,14 +692,105 @@ private:
public:
MeshImporter(ArmatureImporter *arm, Scene *sce) : scene(sce), armature_importer(arm) {}
MTex *assign_textures_to_uvlayer(COLLADAFW::InstanceGeometry::TextureCoordinateBinding &ctexture, Mesh **me, TexIndexTextureArrayMap& texindex_texarray_map, MTex *color_texture)
{
COLLADAFW::TextureMapId texture_index = ctexture.textureMapId;
size_t set_index = ctexture.setIndex;
char *uvname = CustomData_get_layer_name(&(*me)->fdata, CD_MTFACE, set_index);
if (texindex_texarray_map.find(texture_index) == texindex_texarray_map.end()) {
fprintf(stderr, "Cannot find texture array by texture index.\n");
return NULL;
}
// assign uvlayer name to texture
std::vector<MTex*> textures = texindex_texarray_map[texture_index];
std::vector<MTex*>::iterator it;
for (it = textures.begin(); it != textures.end(); it++) {
MTex *texture = *it;
if (texture) {
strcpy(texture->uvname, uvname);
if (texture->mapto == MAP_COL) color_texture = texture;
}
}
return color_texture;
}
MTFace *assign_material_to_geom(COLLADAFW::InstanceGeometry::MaterialBinding cmaterial,
std::map<COLLADAFW::UniqueId, Material*>& uid_material_map,
Object *ob, Mesh *me, const COLLADAFW::UniqueId *geom_uid,
MTex **color_texture, char *layername, MTFace *texture_face,
std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map, int mat_index)
{
const COLLADAFW::UniqueId& ma_uid = cmaterial.getReferencedMaterial();
unsigned int j;
// do we know this material?
if (uid_material_map.find(ma_uid) == uid_material_map.end()) {
fprintf(stderr, "Cannot find material by UID.\n");
return NULL;
}
Material *ma = uid_material_map[ma_uid];
TexIndexTextureArrayMap texindex_texarray_map = material_texture_mapping_map[ma];
COLLADAFW::InstanceGeometry::TextureCoordinateBindingArray& tex_array = cmaterial.getTextureCoordinateBindingArray();
// loop through material's textures
for (j = 0; j < tex_array.getCount(); j++) {
*color_texture = assign_textures_to_uvlayer(tex_array[j], &me, texindex_texarray_map, *color_texture);
}
// if material has color texture
if (*color_texture && strlen((*color_texture)->uvname)) {
// multiple color textures may refer to the same uvlayer,
// set tface only once, otherwise images will rewrite each other
if (strcmp(layername, (*color_texture)->uvname) != 0) {
texture_face = (MTFace*)CustomData_get_layer_named(&me->fdata, CD_MTFACE, (*color_texture)->uvname);
strcpy(layername, (*color_texture)->uvname);
}
}
assign_material(ob, ma, ob->totcol + 1);
MaterialIdPrimitiveArrayMap& mat_prim_map = geom_uid_mat_mapping_map[*geom_uid];
COLLADAFW::MaterialId mat_id = cmaterial.getMaterialId();
// assign material indices to mesh faces
if (mat_prim_map.find(mat_id) != mat_prim_map.end()) {
std::vector<Primitive>& prims = mat_prim_map[mat_id];
std::vector<Primitive>::iterator it;
for (it = prims.begin(); it != prims.end(); it++) {
Primitive& prim = *it;
j = 0;
while (j++ < prim.totface) {
prim.mface->mat_nr = mat_index;
prim.mface++;
// if tface was set
// bind image to tface
if (texture_face && (*color_texture)) {
texture_face->mode = TF_TEX;
texture_face->tpage = (Image*)(*color_texture)->tex->ima;
texture_face++;
}
}
}
}
// bind object with a mesh assigning materials and textures
return texture_face;
}
// bind object to mesh
Object *create_mesh_object(COLLADAFW::Node *node, COLLADAFW::InstanceGeometry *geom,
bool isController, std::map<COLLADAFW::UniqueId, Material*>& uid_material_map)
bool isController,
std::map<COLLADAFW::UniqueId, Material*>& uid_material_map,
std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map)
{
const COLLADAFW::UniqueId *geom_uid = &geom->getInstanciatedObjectId();
// checking if node instanciates controller or geometry
// check if node instanciates controller or geometry
if (isController) {
geom_uid = armature_importer->get_geometry_uid(*geom_uid);
if (!geom_uid) {
@@ -707,9 +806,10 @@ public:
return NULL;
}
}
if (!uid_mesh_map[*geom_uid]) return NULL;
Object *ob = add_object(scene, OB_MESH);
// name Object
const std::string& id = node->getOriginalId();
if (id.length())
@@ -723,107 +823,19 @@ public:
if (old_mesh->id.us == 0) free_libblock(&G.main->mesh, old_mesh);
Mesh *me = (Mesh*)ob->data;
MTex *diffuse_mtex = NULL;
/*
MTFace *tface = NULL;
char layername[100];
bool first_time = true;
*/
MTFace *texture_face = NULL;
MTex *color_texture = NULL;
// assign material indices to mesh faces
for (unsigned int k = 0; k < geom->getMaterialBindings().getCount(); k++) {
COLLADAFW::InstanceGeometry::MaterialBindingArray& mat_array = geom->getMaterialBindings();
// loop through geom's materials
for (unsigned int i = 0; i < mat_array.getCount(); i++) {
texture_face = assign_material_to_geom(mat_array[i], uid_material_map, ob, me, geom_uid, &color_texture, layername, texture_face, material_texture_mapping_map, i);
const COLLADAFW::UniqueId& ma_uid = geom->getMaterialBindings()[k].getReferencedMaterial();
// do we know this material?
if (uid_material_map.find(ma_uid) == uid_material_map.end()) {
fprintf(stderr, "Cannot find material by UID.\n");
continue;
}
Material *ma = uid_material_map[ma_uid];
unsigned int l;
// XXX I don't understand this! (Arystan)
/*
// assign textures to uv layers
// bvi_array "bind_vertex_input array"
COLLADAFW::InstanceGeometry::TextureCoordinateBindingArray& bvi_array =
geom->getMaterialBindings()[k].getTextureCoordinateBindingArray();
for (l = 0; l < bvi_array.getCount(); l++) {
COLLADAFW::TextureMapId tex_index = bvi_array[l].textureMapId;
size_t set_index = bvi_array[l].setIndex;
// if (set_layername_map.find(set_index) == set_layername_map.end()) {
// fprintf(stderr, "Cannot find uvlayer name by set index.\n");
// continue;
// }
// char *uvname = set_layername_map[set_index];
char *uvname = CustomData_get_layer_name(&me->fdata, CD_MTFACE, set_index);
// check if mtexes were properly added to vector
if (index_mtex_map.find(tex_index) == index_mtex_map.end()) {
fprintf(stderr, "Cannot find mtexes by texmap id.\n");
continue;
}
std::vector<MTex*> mtexes = index_mtex_map[tex_index];
std::vector<MTex*>::iterator it;
for (it = mtexes.begin(); it != mtexes.end(); it++) {
MTex *mtex = *it;
if (mtex && mtex->uvname) strcpy(mtex->uvname, uvname);
}
}
for (l = 0; l < 18; l++) {
if (ma->mtex[l] && ma->mtex[l]->mapto == MAP_COL) {
diffuse_mtex = ma->mtex[l];
}
}
if (diffuse_mtex && strlen(diffuse_mtex->uvname)) {
if (first_time) {
tface = (MTFace*)CustomData_get_layer_named(&me->fdata, CD_MTFACE, diffuse_mtex->uvname);
strcpy(layername, diffuse_mtex->uvname);
first_time = false;
}
else if (strcmp(diffuse_mtex->uvname, layername) != 0) {
tface = (MTFace*)CustomData_get_layer_named(&me->fdata, CD_MTFACE, diffuse_mtex->uvname);
strcpy(layername, diffuse_mtex->uvname);
}
}
*/
assign_material(ob, ma, ob->totcol + 1);
MaterialIdPrimitiveArrayMap& mat_prim_map = geom_uid_mat_mapping_map[*geom_uid];
COLLADAFW::MaterialId mat_id = geom->getMaterialBindings()[k].getMaterialId();
// set material index on each face
if (mat_prim_map.find(mat_id) != mat_prim_map.end()) {
std::vector<Primitive>& prims = mat_prim_map[mat_id];
std::vector<Primitive>::iterator it;
for (it = prims.begin(); it != prims.end(); it++) {
Primitive& prim = *it;
l = 0;
while (l++ < prim.totface) {
prim.mface->mat_nr = k;
prim.mface++;
/*
// if tface was set
// bind image to tface
if (tface) {
tface->mode = TF_TEX;
tface->tpage = (Image*)diffuse_mtex->tex->ima;
tface++;
}
*/
}
}
}
}
return ob;
}
@@ -858,8 +870,8 @@ public:
read_faces(mesh, me);
mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
make_edges(me, 0);
mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
// make_edges(me, 0);
return true;
}
@@ -891,7 +903,9 @@ private:
std::map<COLLADAFW::UniqueId, Material*> uid_effect_map;
std::map<COLLADAFW::UniqueId, Camera*> uid_camera_map;
std::map<COLLADAFW::UniqueId, Lamp*> uid_lamp_map;
// maps for assigning textures to uv layers
//std::map<COLLADAFW::TextureMapId, char*> set_layername_map;
std::map<Material*, TexIndexTextureArrayMap> material_texture_mapping_map;
// animation
std::map<COLLADAFW::UniqueId, std::vector<FCurve*> > uid_fcurve_map;
struct AnimatedTransform {
@@ -991,7 +1005,7 @@ public:
// <instance_geometry>
if (geom.getCount() != 0) {
ob = mesh_importer.create_mesh_object(node, geom[0], false, uid_material_map);
ob = mesh_importer.create_mesh_object(node, geom[0], false, uid_material_map, material_texture_mapping_map);
}
// <instance_camera>
else if (camera.getCount() != 0) {
@@ -1024,7 +1038,7 @@ public:
// <instance_controller>
else if (controller.getCount() != 0) {
COLLADAFW::InstanceController *geom = (COLLADAFW::InstanceController*)controller[0];
ob = mesh_importer.create_mesh_object(node, geom, true, uid_material_map);
ob = mesh_importer.create_mesh_object(node, geom, true, uid_material_map, material_texture_mapping_map);
}
// XXX <node> - this is not supported yet
else if (inst_node.getCount() != 0) {
@@ -1046,14 +1060,15 @@ public:
// doing what 'set parent' operator does
par->recalc |= OB_RECALC_OB;
ob->parsubstr[0] = 0;
DAG_scene_sort(sce);
// since ob->obmat is identity, this is not needed?
what_does_parent(sce, ob, &workob);
/*what_does_parent(sce, ob, &workob);
Mat4Invert(ob->parentinv, workob.obmat);
ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
ob->partype = PAROBJECT;
DAG_scene_sort(sce);
DAG_scene_sort(sce);*/
}
// transform Object
float rot[3][3];
@@ -1190,7 +1205,7 @@ public:
}
// create mtex, create texture, set texture image
MTex *create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::Texture ctex, Material *ma, int i)
MTex *create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::Texture &ctex, Material *ma, int i, TexIndexTextureArrayMap &texindex_texarray_map)
{
COLLADAFW::SamplerPointerArray& samp_array = ef->getSamplerPointerArray();
COLLADAFW::Sampler *sampler = samp_array[ctex.getSamplerId()];
@@ -1207,33 +1222,14 @@ public:
ma->mtex[i]->tex = add_texture("texture");
ma->mtex[i]->tex->type = TEX_IMAGE;
ma->mtex[i]->tex->ima = uid_image_map[ima_uid];
// index_mtex_map[ctex.getTextureMapId()].push_back(ma->mtex[i]);
texindex_texarray_map[ctex.getTextureMapId()].push_back(ma->mtex[i]);
return ma->mtex[i];
}
/** When this method is called, the writer must write the effect.
@return The writer should return true, if writing succeeded, false otherwise.*/
virtual bool writeEffect( const COLLADAFW::Effect* effect )
void write_profile_COMMON(COLLADAFW::EffectCommon *ef, Material *ma)
{
const COLLADAFW::UniqueId& uid = effect->getUniqueId();
if (uid_effect_map.find(uid) == uid_effect_map.end()) {
fprintf(stderr, "Couldn't find a material by UID.\n");
return true;
}
Material *ma = uid_effect_map[uid];
COLLADAFW::CommonEffectPointerArray common_efs = effect->getCommonEffects();
if (common_efs.getCount() < 1) {
fprintf(stderr, "<effect> hasn't got <profile_COMMON>s.\n Currently we support only them. \n");
return true;
}
// XXX TODO: Take all <profile_common>s
// Currently only first <profile_common> is supported
COLLADAFW::EffectCommon *ef = common_efs[0];
COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType();
// blinn
@@ -1264,6 +1260,7 @@ public:
COLLADAFW::Color col;
COLLADAFW::Texture ctex;
MTex *mtex = NULL;
TexIndexTextureArrayMap texindex_texarray_map;
// DIFFUSE
// color
@@ -1276,7 +1273,7 @@ public:
// texture
else if (ef->getDiffuse().isTexture()) {
ctex = ef->getDiffuse().getTexture();
mtex = create_texture(ef, ctex, ma, i);
mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
if (mtex != NULL) {
mtex->mapto = MAP_COL;
ma->texact = (int)i;
@@ -1294,7 +1291,7 @@ public:
// texture
else if (ef->getAmbient().isTexture()) {
ctex = ef->getAmbient().getTexture();
mtex = create_texture(ef, ctex, ma, i);
mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
if (mtex != NULL) {
mtex->mapto = MAP_AMB;
i++;
@@ -1311,7 +1308,7 @@ public:
// texture
else if (ef->getSpecular().isTexture()) {
ctex = ef->getSpecular().getTexture();
mtex = create_texture(ef, ctex, ma, i);
mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
if (mtex != NULL) {
mtex->mapto = MAP_SPEC;
i++;
@@ -1328,7 +1325,7 @@ public:
// texture
else if (ef->getReflective().isTexture()) {
ctex = ef->getReflective().getTexture();
mtex = create_texture(ef, ctex, ma, i);
mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
if (mtex != NULL) {
mtex->mapto = MAP_REF;
i++;
@@ -1343,12 +1340,37 @@ public:
// texture
else if (ef->getEmission().isTexture()) {
ctex = ef->getEmission().getTexture();
mtex = create_texture(ef, ctex, ma, i);
mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
if (mtex != NULL) {
mtex->mapto = MAP_EMIT;
i++;
}
}
material_texture_mapping_map[ma] = texindex_texarray_map;
}
/** When this method is called, the writer must write the effect.
@return The writer should return true, if writing succeeded, false otherwise.*/
virtual bool writeEffect( const COLLADAFW::Effect* effect )
{
const COLLADAFW::UniqueId& uid = effect->getUniqueId();
if (uid_effect_map.find(uid) == uid_effect_map.end()) {
fprintf(stderr, "Couldn't find a material by UID.\n");
return true;
}
Material *ma = uid_effect_map[uid];
COLLADAFW::CommonEffectPointerArray common_efs = effect->getCommonEffects();
if (common_efs.getCount() < 1) {
fprintf(stderr, "<effect> hasn't got <profile_COMMON>s.\n Currently we support only them. \n");
return true;
}
// XXX TODO: Take all <profile_common>s
// Currently only first <profile_common> is supported
COLLADAFW::EffectCommon *ef = common_efs[0];
write_profile_COMMON(ef, ma);
return true;
}