Beispiel #1
0
/**
 * We do not know in advance which objects will share geometries.
 * And we do not know either if the objects which share geometries
 * come along with different materials. So we first create the objects
 * and assign the materials to Object, then in a later cleanup we decide
 * which materials shall be moved to the created geometries. Also see
 * optimize_material_assignements() above.
 */
MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial,
                                              std::map<COLLADAFW::UniqueId, Material *>& uid_material_map,
                                              Object *ob, const COLLADAFW::UniqueId *geom_uid,
                                              char *layername, MTFace *texture_face,
                                              std::map<Material *, TexIndexTextureArrayMap>& material_texture_mapping_map, short mat_index)
{
	MTex *color_texture = NULL;
	Mesh *me = (Mesh *)ob->data;
	const COLLADAFW::UniqueId& ma_uid = cmaterial.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");
		return NULL;
	}

	// first time we get geom_uid, ma_uid pair. Save for later check.
	materials_mapped_to_geom.insert(std::pair<COLLADAFW::UniqueId, COLLADAFW::UniqueId>(*geom_uid, ma_uid));
	
	Material *ma = uid_material_map[ma_uid];

	// Attention! This temporaly assigns material to object on purpose!
	// See note above.
	ob->actcol=0;
	assign_material(ob, ma, mat_index + 1, BKE_MAT_ASSIGN_OBJECT); 
	
	COLLADAFW::TextureCoordinateBindingArray& tex_array = 
	    cmaterial.getTextureCoordinateBindingArray();
	TexIndexTextureArrayMap texindex_texarray_map = material_texture_mapping_map[ma];
	unsigned int i;
	// loop through <bind_vertex_inputs>
	for (i = 0; i < tex_array.getCount(); i++) {
		
		color_texture = assign_textures_to_uvlayer(tex_array[i], me, texindex_texarray_map,
		                                            color_texture);
	}
	
	// set texture face
	if (color_texture &&
	    strlen((color_texture)->uvname) &&
	    !STREQ(layername, color_texture->uvname)) {
		texture_face = (MTFace *)CustomData_get_layer_named(&me->fdata, CD_MTFACE,
		                                                    color_texture->uvname);
		strcpy(layername, color_texture->uvname);
	}
	
	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;
			MPoly *mpoly = prim.mpoly;

			for (i = 0; i < prim.totpoly; i++, mpoly++) {
				mpoly->mat_nr = mat_index;
				// bind texture images to faces
				if (texture_face && color_texture) {
					texture_face->tpage = (Image *)color_texture->tex->ima;
					texture_face++;
				}
			}
		}
	}	
	return texture_face;
}
Beispiel #2
0
void get_texture_coords(MappingInfoModifierData *dmd, Object *ob,
                        DerivedMesh *dm,
                        float (*co)[3], float (*texco)[3],
                        int numVerts)
{
	int i;
	int texmapping = dmd->texmapping;
	float mapob_imat[4][4];

	if(texmapping == MOD_DISP_MAP_OBJECT) {
		if(dmd->map_object)
			invert_m4_m4(mapob_imat, dmd->map_object->obmat);
		else /* if there is no map object, default to local */
			texmapping = MOD_DISP_MAP_LOCAL;
	}

	/* UVs need special handling, since they come from faces */
	if(texmapping == MOD_DISP_MAP_UV) {
		if(CustomData_has_layer(&dm->faceData, CD_MTFACE)) {
			MFace *mface = dm->getFaceArray(dm);
			MFace *mf;
			char *done = MEM_callocN(sizeof(*done) * numVerts,
			                         "get_texture_coords done");
			int numFaces = dm->getNumFaces(dm);
			char uvname[32];
			MTFace *tf;

			validate_layer_name(&dm->faceData, CD_MTFACE, dmd->uvlayer_name, uvname);
			tf = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, uvname);

			/* verts are given the UV from the first face that uses them */
			for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
				if(!done[mf->v1]) {
					texco[mf->v1][0] = tf->uv[0][0];
					texco[mf->v1][1] = tf->uv[0][1];
					texco[mf->v1][2] = 0;
					done[mf->v1] = 1;
				}
				if(!done[mf->v2]) {
					texco[mf->v2][0] = tf->uv[1][0];
					texco[mf->v2][1] = tf->uv[1][1];
					texco[mf->v2][2] = 0;
					done[mf->v2] = 1;
				}
				if(!done[mf->v3]) {
					texco[mf->v3][0] = tf->uv[2][0];
					texco[mf->v3][1] = tf->uv[2][1];
					texco[mf->v3][2] = 0;
					done[mf->v3] = 1;
				}
				if(!done[mf->v4]) {
					texco[mf->v4][0] = tf->uv[3][0];
					texco[mf->v4][1] = tf->uv[3][1];
					texco[mf->v4][2] = 0;
					done[mf->v4] = 1;
				}
			}

			/* remap UVs from [0, 1] to [-1, 1] */
			for(i = 0; i < numVerts; ++i) {
				texco[i][0] = texco[i][0] * 2 - 1;
				texco[i][1] = texco[i][1] * 2 - 1;
			}

			MEM_freeN(done);
			return;
		} else /* if there are no UVs, default to local */
			texmapping = MOD_DISP_MAP_LOCAL;
	}

	for(i = 0; i < numVerts; ++i, ++co, ++texco) {
		switch(texmapping) {
		case MOD_DISP_MAP_LOCAL:
			copy_v3_v3(*texco, *co);
			break;
		case MOD_DISP_MAP_GLOBAL:
			mul_v3_m4v3(*texco, ob->obmat, *co);
			break;
		case MOD_DISP_MAP_OBJECT:
			mul_v3_m4v3(*texco, ob->obmat, *co);
			mul_m4_v3(mapob_imat, *texco);
			break;
		}
	}
}
Beispiel #3
0
static DerivedMesh *explodeMesh(ExplodeModifierData *emd,
                                ParticleSystemModifierData *psmd, Scene *scene, Object *ob,
                                DerivedMesh *to_explode)
{
    DerivedMesh *explode, *dm = to_explode;
    MFace *mf = NULL, *mface;
    /* ParticleSettings *part=psmd->psys->part; */ /* UNUSED */
    ParticleSimulationData sim = {NULL};
    ParticleData *pa = NULL, *pars = psmd->psys->particles;
    ParticleKey state, birth;
    EdgeHash *vertpahash;
    EdgeHashIterator *ehi;
    float *vertco = NULL, imat[4][4];
    float rot[4];
    float cfra;
    /* float timestep; */
    const int *facepa = emd->facepa;
    int totdup = 0, totvert = 0, totface = 0, totpart = 0, delface = 0;
    int i, v, u;
    unsigned int ed_v1, ed_v2, mindex = 0;
    MTFace *mtface = NULL, *mtf;

    totface = dm->getNumTessFaces(dm);
    totvert = dm->getNumVerts(dm);
    mface = dm->getTessFaceArray(dm);
    totpart = psmd->psys->totpart;

    sim.scene = scene;
    sim.ob = ob;
    sim.psys = psmd->psys;
    sim.psmd = psmd;

    /* timestep = psys_get_timestep(&sim); */

    cfra = BKE_scene_frame_get(scene);

    /* hash table for vertice <-> particle relations */
    vertpahash = BLI_edgehash_new(__func__);

    for (i = 0; i < totface; i++) {
        if (facepa[i] != totpart) {
            pa = pars + facepa[i];

            if ((pa->alive == PARS_UNBORN && (emd->flag & eExplodeFlag_Unborn) == 0) ||
                    (pa->alive == PARS_ALIVE && (emd->flag & eExplodeFlag_Alive) == 0) ||
                    (pa->alive == PARS_DEAD && (emd->flag & eExplodeFlag_Dead) == 0))
            {
                delface++;
                continue;
            }
        }

        /* do mindex + totvert to ensure the vertex index to be the first
         * with BLI_edgehashIterator_getKey */
        if (facepa[i] == totpart || cfra < (pars + facepa[i])->time)
            mindex = totvert + totpart;
        else
            mindex = totvert + facepa[i];

        mf = &mface[i];

        /* set face vertices to exist in particle group */
        BLI_edgehash_reinsert(vertpahash, mf->v1, mindex, NULL);
        BLI_edgehash_reinsert(vertpahash, mf->v2, mindex, NULL);
        BLI_edgehash_reinsert(vertpahash, mf->v3, mindex, NULL);
        if (mf->v4)
            BLI_edgehash_reinsert(vertpahash, mf->v4, mindex, NULL);
    }

    /* make new vertice indexes & count total vertices after duplication */
    ehi = BLI_edgehashIterator_new(vertpahash);
    for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
        BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(totdup));
        totdup++;
    }
    BLI_edgehashIterator_free(ehi);

    /* the final duplicated vertices */
    explode = CDDM_from_template_ex(dm, totdup, 0, totface - delface, 0, 0, CD_MASK_DERIVEDMESH | CD_MASK_FACECORNERS);
    mtface = CustomData_get_layer_named(&explode->faceData, CD_MTFACE, emd->uvname);
    /*dupvert = CDDM_get_verts(explode);*/

    /* getting back to object space */
    invert_m4_m4(imat, ob->obmat);

    psmd->psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);

    /* duplicate & displace vertices */
    ehi = BLI_edgehashIterator_new(vertpahash);
    for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
        MVert source;
        MVert *dest;

        /* get particle + vertex from hash */
        BLI_edgehashIterator_getKey(ehi, &ed_v1, &ed_v2);
        ed_v2 -= totvert;
        v = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));

        dm->getVert(dm, ed_v1, &source);
        dest = CDDM_get_vert(explode, v);

        DM_copy_vert_data(dm, explode, ed_v1, v, 1);
        *dest = source;

        if (ed_v2 != totpart) {
            /* get particle */
            pa = pars + ed_v2;

            psys_get_birth_coords(&sim, pa, &birth, 0, 0);

            state.time = cfra;
            psys_get_particle_state(&sim, ed_v2, &state, 1);

            vertco = CDDM_get_vert(explode, v)->co;
            mul_m4_v3(ob->obmat, vertco);

            sub_v3_v3(vertco, birth.co);

            /* apply rotation, size & location */
            sub_qt_qtqt(rot, state.rot, birth.rot);
            mul_qt_v3(rot, vertco);

            if (emd->flag & eExplodeFlag_PaSize)
                mul_v3_fl(vertco, pa->size);

            add_v3_v3(vertco, state.co);

            mul_m4_v3(imat, vertco);
        }
    }
    BLI_edgehashIterator_free(ehi);

    /*map new vertices to faces*/
    for (i = 0, u = 0; i < totface; i++) {
        MFace source;
        int orig_v4;

        if (facepa[i] != totpart) {
            pa = pars + facepa[i];

            if (pa->alive == PARS_UNBORN && (emd->flag & eExplodeFlag_Unborn) == 0) continue;
            if (pa->alive == PARS_ALIVE && (emd->flag & eExplodeFlag_Alive) == 0) continue;
            if (pa->alive == PARS_DEAD && (emd->flag & eExplodeFlag_Dead) == 0) continue;
        }

        dm->getTessFace(dm, i, &source);
        mf = CDDM_get_tessface(explode, u);

        orig_v4 = source.v4;

        if (facepa[i] != totpart && cfra < pa->time)
            mindex = totvert + totpart;
        else
            mindex = totvert + facepa[i];

        source.v1 = edgecut_get(vertpahash, source.v1, mindex);
        source.v2 = edgecut_get(vertpahash, source.v2, mindex);
        source.v3 = edgecut_get(vertpahash, source.v3, mindex);
        if (source.v4)
            source.v4 = edgecut_get(vertpahash, source.v4, mindex);

        DM_copy_tessface_data(dm, explode, i, u, 1);

        *mf = source;

        /* override uv channel for particle age */
        if (mtface) {
            float age = (cfra - pa->time) / pa->lifetime;
            /* Clamp to this range to avoid flipping to the other side of the coordinates. */
            CLAMP(age, 0.001f, 0.999f);

            mtf = mtface + u;

            mtf->uv[0][0] = mtf->uv[1][0] = mtf->uv[2][0] = mtf->uv[3][0] = age;
            mtf->uv[0][1] = mtf->uv[1][1] = mtf->uv[2][1] = mtf->uv[3][1] = 0.5f;
        }

        test_index_face(mf, &explode->faceData, u, (orig_v4 ? 4 : 3));
        u++;
    }

    /* cleanup */
    BLI_edgehash_free(vertpahash, NULL);

    /* finalization */
    CDDM_calc_edges_tessface(explode);
    CDDM_tessfaces_to_faces(explode);
    explode->dirty |= DM_DIRTY_NORMALS;

    if (psmd->psys->lattice_deform_data) {
        end_latt_deform(psmd->psys->lattice_deform_data);
        psmd->psys->lattice_deform_data = NULL;
    }

    return explode;
}
Beispiel #4
0
void get_texture_coords(MappingInfoModifierData *dmd, Object *ob,
                        DerivedMesh *dm,
                        float (*co)[3], float (*texco)[3],
                        int numVerts)
{
	int i;
	int texmapping = dmd->texmapping;
	float mapob_imat[4][4];

	if (texmapping == MOD_DISP_MAP_OBJECT) {
		if (dmd->map_object)
			invert_m4_m4(mapob_imat, dmd->map_object->obmat);
		else /* if there is no map object, default to local */
			texmapping = MOD_DISP_MAP_LOCAL;
	}

	/* UVs need special handling, since they come from faces */
	if (texmapping == MOD_DISP_MAP_UV) {
		if (CustomData_has_layer(&dm->loopData, CD_MLOOPUV)) {
			MPoly *mpoly = dm->getPolyArray(dm);
			MPoly *mp;
			MLoop *mloop = dm->getLoopArray(dm);
			char *done = MEM_calloc_arrayN(numVerts, sizeof(*done),
			                         "get_texture_coords done");
			int numPolys = dm->getNumPolys(dm);
			char uvname[MAX_CUSTOMDATA_LAYER_NAME];
			MLoopUV *mloop_uv;

			CustomData_validate_layer_name(&dm->loopData, CD_MLOOPUV, dmd->uvlayer_name, uvname);
			mloop_uv = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV, uvname);

			/* verts are given the UV from the first face that uses them */
			for (i = 0, mp = mpoly; i < numPolys; ++i, ++mp) {
				unsigned int fidx = mp->totloop - 1;

				do {
					unsigned int lidx = mp->loopstart + fidx;
					unsigned int vidx = mloop[lidx].v;

					if (done[vidx] == 0) {
						/* remap UVs from [0, 1] to [-1, 1] */
						texco[vidx][0] = (mloop_uv[lidx].uv[0] * 2.0f) - 1.0f;
						texco[vidx][1] = (mloop_uv[lidx].uv[1] * 2.0f) - 1.0f;
						done[vidx] = 1;
					}

				} while (fidx--);
			}

			MEM_freeN(done);
			return;
		}
		else /* if there are no UVs, default to local */
			texmapping = MOD_DISP_MAP_LOCAL;
	}

	for (i = 0; i < numVerts; ++i, ++co, ++texco) {
		switch (texmapping) {
			case MOD_DISP_MAP_LOCAL:
				copy_v3_v3(*texco, *co);
				break;
			case MOD_DISP_MAP_GLOBAL:
				mul_v3_m4v3(*texco, ob->obmat, *co);
				break;
			case MOD_DISP_MAP_OBJECT:
				mul_v3_m4v3(*texco, ob->obmat, *co);
				mul_m4_v3(mapob_imat, *texco);
				break;
		}
	}
}
// =======================================================================
// Read all faces from TRIANGLES, TRIANGLE_FANS, POLYLIST, POLYGON
// Important: This function MUST be called before read_lines() 
// Otherwise we will loose all edges from faces (see read_lines() above)
//
// TODO: import uv set names
// ========================================================================
void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me)
{
	unsigned int i;
	
	allocate_poly_data(collada_mesh, me);

	UVDataWrapper uvs(collada_mesh->getUVCoords());

	MPoly *mpoly = me->mpoly;
	MLoop *mloop = me->mloop;
	int loop_index = 0;

	MaterialIdPrimitiveArrayMap mat_prim_map;

	COLLADAFW::MeshPrimitiveArray& prim_arr = collada_mesh->getMeshPrimitives();
	COLLADAFW::MeshVertexData& nor = collada_mesh->getNormals();

	for (i = 0; i < prim_arr.getCount(); i++) {
		
		COLLADAFW::MeshPrimitive *mp = prim_arr[i];

		// faces
		size_t prim_totpoly            = mp->getFaceCount();
		unsigned int *position_indices = mp->getPositionIndices().getData();
		unsigned int *normal_indices   = mp->getNormalIndices().getData();

		bool mp_has_normals = primitive_has_useable_normals(mp);
		bool mp_has_faces   = primitive_has_faces(mp);

		int collada_meshtype = mp->getPrimitiveType();
		
		// since we cannot set mpoly->mat_nr here, we store a portion of me->mpoly in Primitive
		Primitive prim = {mpoly, 0};
		COLLADAFW::IndexListArray& index_list_array = mp->getUVCoordIndicesArray();

		// If MeshPrimitive is TRIANGLE_FANS we split it into triangles
		// The first trifan vertex will be the first vertex in every triangle
		// XXX The proper function of TRIANGLE_FANS is not tested!!!
		// XXX In particular the handling of the normal_indices looks very wrong to me
		if (collada_meshtype == COLLADAFW::MeshPrimitive::TRIANGLE_FANS) {
			unsigned grouped_vertex_count = mp->getGroupedVertexElementsCount();
			for (unsigned int group_index = 0; group_index < grouped_vertex_count; group_index++) {
				unsigned int first_vertex = position_indices[0]; // Store first trifan vertex
				unsigned int first_normal = normal_indices[0]; // Store first trifan vertex normal
				unsigned int vertex_count = mp->getGroupedVerticesVertexCount(group_index);

				for (unsigned int vertex_index = 0; vertex_index < vertex_count - 2; vertex_index++) {
					// For each triangle store indeces of its 3 vertices
					unsigned int triangle_vertex_indices[3] = {first_vertex, position_indices[1], position_indices[2]};
					set_poly_indices(mpoly, mloop, loop_index, triangle_vertex_indices, 3);

					if (mp_has_normals) {  // vertex normals, same inplementation as for the triangles
						// the same for vertces normals
						unsigned int vertex_normal_indices[3] = {first_normal, normal_indices[1], normal_indices[2]};
						if (!is_flat_face(vertex_normal_indices, nor, 3))
							mpoly->flag |= ME_SMOOTH;
						normal_indices++;
					}
				
					mpoly++;
					mloop += 3;
					loop_index += 3;
					prim.totpoly++;

				}

				// Moving cursor  to the next triangle fan.
				if (mp_has_normals)
					normal_indices += 2;

				position_indices +=  2;
			}
		}

		if (collada_meshtype == COLLADAFW::MeshPrimitive::POLYLIST ||
			collada_meshtype == COLLADAFW::MeshPrimitive::POLYGONS ||
			collada_meshtype == COLLADAFW::MeshPrimitive::TRIANGLES) {
			COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
			unsigned int start_index = 0;

			for (unsigned int j = 0; j < prim_totpoly; j++) {
				
				// Vertices in polygon:
				int vcount = get_vertex_count(mpvc, j);
				set_poly_indices(mpoly, mloop, loop_index, position_indices, vcount);


				for (unsigned int uvset_index = 0; uvset_index < index_list_array.getCount(); uvset_index++) {
					// get mtface by face index and uv set index
					COLLADAFW::IndexList& index_list = *index_list_array[uvset_index];
					MLoopUV  *mloopuv = (MLoopUV  *)CustomData_get_layer_named(&me->ldata, CD_MLOOPUV, index_list.getName().c_str());
					if (mloopuv == NULL) {
						fprintf(stderr, "Collada import: Mesh [%s] : Unknown reference to TEXCOORD [#%s].", me->id.name, index_list.getName().c_str() );
					}
					else {
						set_face_uv(mloopuv+loop_index, uvs, start_index, *index_list_array[uvset_index], vcount);
					}
				}

				if (mp_has_normals) {
					if (!is_flat_face(normal_indices, nor, vcount))
						mpoly->flag |= ME_SMOOTH;
				}
				
				mpoly++;
				mloop += vcount;
				loop_index += vcount;
				start_index += vcount;
				prim.totpoly++;

				if (mp_has_normals)
					normal_indices += vcount;

				position_indices += vcount;
			}
		}

		else if (collada_meshtype == COLLADAFW::MeshPrimitive::LINES) {
			continue; // read the lines later after all the rest is done
		}

		if (mp_has_faces)
			mat_prim_map[mp->getMaterialId()].push_back(prim);
	}

	geom_uid_mat_mapping_map[collada_mesh->getUniqueId()] = mat_prim_map;
}