// =================================================================
// Read all loose edges.
// Important: This function assumes that all edges from existing 
// faces have allready been generated and added to me->medge
// So this function MUST be called after read_faces() (see below)
// =================================================================
void MeshImporter::read_lines(COLLADAFW::Mesh *mesh, Mesh *me)
{
	unsigned int loose_edge_count = get_loose_edge_count(mesh);
	if (loose_edge_count > 0) {

		unsigned int face_edge_count  = me->totedge;
		/* unsigned int total_edge_count = loose_edge_count + face_edge_count; */ /* UNUSED */
		
		mesh_add_edges(me, loose_edge_count);
		MEdge *med = me->medge + face_edge_count;

		COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();

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

			int type = mp->getPrimitiveType();
			if (type == COLLADAFW::MeshPrimitive::LINES) {
				unsigned int edge_count  = mp->getFaceCount();
				unsigned int *indices    = mp->getPositionIndices().getData();
				
				for (int i = 0; i < edge_count; i++, med++) {
					med->bweight = 0;
					med->crease  = 0;
					med->flag   |= ME_LOOSEEDGE;
					med->v1      = indices[2 * i];
					med->v2      = indices[2 * i + 1];
				}
			}
		}

	}
}
Beispiel #2
0
bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh)  // checks if mesh has supported primitive types: lines, polylist, triangles, triangle_fans
{
	COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();

	const std::string &name = bc_get_dae_name(mesh);
	int hole_count = 0;

	for (unsigned i = 0; i < prim_arr.getCount(); i++) {
		
		COLLADAFW::MeshPrimitive *mp = prim_arr[i];
		COLLADAFW::MeshPrimitive::PrimitiveType type = mp->getPrimitiveType();

		const char *type_str = bc_primTypeToStr(type);
		
		// OpenCollada passes POLYGONS type for <polylist>
		if (type == COLLADAFW::MeshPrimitive::POLYLIST || type == COLLADAFW::MeshPrimitive::POLYGONS) {

			COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
			COLLADAFW::Polygons::VertexCountArray& vca = mpvc->getGroupedVerticesVertexCountArray();
			
			for (unsigned int j = 0; j < vca.getCount(); j++) {
				int count = vca[j];
				if (abs(count) < 3) {
					fprintf(stderr, "ERROR: Primitive %s in %s has at least one face with vertex count < 3\n",
					        type_str, name.c_str());
					return false;
				}
				if (count < 0)
				{
					hole_count ++;
				}
			}

			if (hole_count > 0)
			{
				fprintf(stderr, "WARNING: Primitive %s in %s: %d holes not imported (unsupported)\n", type_str, name.c_str(), hole_count);
			}
		}

		else if (type == COLLADAFW::MeshPrimitive::LINES) {
			// TODO: Add Checker for line syntax here
		}

		else if (type != COLLADAFW::MeshPrimitive::TRIANGLES && type != COLLADAFW::MeshPrimitive::TRIANGLE_FANS) {
			fprintf(stderr, "ERROR: Primitive type %s is not supported.\n", type_str);
			return false;
		}
	}
	
	if (mesh->getPositions().empty()) {
		fprintf(stderr, "ERROR: Mesh %s has no vertices.\n", name.c_str());
		return false;
	}

	return true;
}
Beispiel #3
0
unsigned int MeshImporter::get_loose_edge_count(COLLADAFW::Mesh *mesh) {
	COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
	int loose_edge_count = 0;

	// collect edge_count and face_count from all parts
	for (int i = 0; i < prim_arr.getCount(); i++) {
		COLLADAFW::MeshPrimitive *mp = prim_arr[i];
		int type = mp->getPrimitiveType();
		switch (type) {
			case COLLADAFW::MeshPrimitive::LINES: {
				size_t prim_totface = mp->getFaceCount();
				loose_edge_count += prim_totface;
				break;
			}
			default: break;
		}
	}
	return loose_edge_count;
}
SubMesh* ColladaSubMeshReader::Load( void )
{  
	COLLADAFW::MeshPrimitiveArray& primitives = m_pMesh->getMeshPrimitives();

	//若没有几何图元信息
	if( 0 == primitives.getCount() )
	{
		return NULL;
	}

	COLLADAFW::MeshPrimitive* pPrimitive = primitives[0]; 
 
	if(  COLLADAFW::MeshPrimitive::TRIANGLES != pPrimitive->getPrimitiveType()  )
	{
		return NULL;
	}

	COLLADAFW::UIntValuesArray& positionIndices = pPrimitive->getPositionIndices(); 
	//若没有位置索引 则直接退出
	if( 0 == positionIndices.getCount() )
	{
		return NULL;
	} 

	COLLADAFW::UIntValuesArray& normalIndices = pPrimitive->getNormalIndices(); 
	m_bHasNormals = ( normalIndices.getCount() != 0 );  
	COLLADAFW::UIntValuesArray& tangentIndices = pPrimitive->getTangentIndices(); 
	m_bHasTangents = ( tangentIndices.getCount() != 0 ); 
	COLLADAFW::UIntValuesArray& binormalIndices = pPrimitive->getBinormalIndices(); 
	m_bHasBinormals = ( binormalIndices.getCount() != 0 );
	COLLADAFW::IndexList* pUVs = NULL;
	if( pPrimitive->getUVCoordIndicesArray().getCount() )
	{
		pUVs = pPrimitive->getUVCoordIndicesArray()[0]; 
		m_bHasUVs = ( pUVs->getIndices().getCount() != 0 );
	} 

	SubMesh* pSubMesh = new SubMesh;
	pSubMesh->SetName( m_pMesh->getName() );  
	Resource::Material* pMaterial = Resource::MaterialManager::GetInstance()->CreateOrRetrieveMaterial( m_pMesh->getName() );
	pSubMesh->SetMaterial( pMaterial );

	Render::VertexBuffer& vertexBuf =  pSubMesh->RenderData().VertexBuf();
	pSubMesh->RenderData().PrimitiveType( Render::TYPE_TRIANGLES );

	vertexBuf.ChannelFlag() = Render::POSITION_CH;
	if( m_bHasNormals )
	{
		vertexBuf.ChannelFlag() |= Render::NORMAL_CH;
	}
	if( m_bHasUVs )
	{
		vertexBuf.ChannelFlag() |= Render::TEXCOORD_CH;
	}
	if( m_bHasTangents )
	{
		vertexBuf.ChannelFlag() |= Render::TANGENT_CH;
	}
	if( m_bHasBinormals )
	{
		vertexBuf.ChannelFlag() |= Render::BINORMAL_CH;
	}

	unsigned int uiCurrIndex = 0;
	unsigned int uiIndicesCount = positionIndices.getCount();

	for( unsigned int uiIndex = 0 ; uiIndex < uiIndicesCount ; uiIndex++ )
	{
		Tuple tuple;
		tuple.m_posIndex = positionIndices[uiIndex];
		if( m_bHasNormals )
		{
			tuple.m_normIndex = normalIndices[uiIndex];
		}
		if( m_bHasUVs )
		{
			tuple.m_uvIndex = pUVs->getIndices()[uiIndex];
		}
		if( m_bHasTangents )
		{
			tuple.m_tangentIndex = tangentIndices[uiIndex];
		}
		if( m_bHasBinormals )
		{
			tuple.m_binormalIndex = binormalIndices[uiIndex];
		}

		indicesTable_t::iterator itIndex = m_indicesMap.find(tuple); 
		if( itIndex == m_indicesMap.end() )
		{
			Render::Vertex newVert;
			LoadVertexByTuple( tuple , newVert );
			vertexBuf.AppendVertex( newVert );
			m_indicesMap.insert( std::make_pair( tuple , uiCurrIndex ) );
			pSubMesh->RenderData().AppendIndex( uiCurrIndex );
			uiCurrIndex++;
		}else{
			pSubMesh->RenderData().AppendIndex( itIndex->second );
		}

	}//for( unsigned int uiIndex = 0 ; uiIndex < uiIndicesCount ; uiIndex++ )

	return pSubMesh;
}
// =======================================================================
// 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());
	VCOLDataWrapper vcol(collada_mesh->getColors());

	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};

		// 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;

			COLLADAFW::IndexListArray& index_list_array_uvcoord = mp->getUVCoordIndicesArray();
			COLLADAFW::IndexListArray& index_list_array_vcolor  = mp->getColorIndicesArray();

			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_uvcoord.getCount(); uvset_index++) {
					// get mtface by face index and uv set index
					COLLADAFW::IndexList& index_list = *index_list_array_uvcoord[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].\n", me->id.name, index_list.getName().c_str() );
					}
					else {
						set_face_uv(mloopuv+loop_index, uvs, start_index, *index_list_array_uvcoord[uvset_index], vcount);
					}
				}

				if (mp_has_normals) {
					if (!is_flat_face(normal_indices, nor, vcount))
						mpoly->flag |= ME_SMOOTH;
				}


				if (mp->hasColorIndices()) {
					int vcolor_count = index_list_array_vcolor.getCount();

					for (unsigned int vcolor_index = 0; vcolor_index < vcolor_count; vcolor_index++) {

						COLLADAFW::IndexList& color_index_list = *mp->getColorIndices(vcolor_index);
						COLLADAFW::String colname = extract_vcolname(color_index_list.getName());
						MLoopCol *mloopcol = (MLoopCol  *)CustomData_get_layer_named(&me->ldata, CD_MLOOPCOL, colname.c_str());
						if (mloopcol == NULL) {
							fprintf(stderr, "Collada import: Mesh [%s] : Unknown reference to VCOLOR [#%s].\n", me->id.name, color_index_list.getName().c_str());
						}
						else {
							set_vcol(mloopcol + loop_index, vcol, start_index, color_index_list, vcount);
						}
					}
				}

				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;
}
// =================================================================
// Return the number of faces by summing up
// the facecounts of the parts.
// hint: This is done because mesh->getFacesCount() does
// count loose edges as extra faces, which is not what we want here.
// =================================================================
void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me)
{
	COLLADAFW::MeshPrimitiveArray& prim_arr = collada_mesh->getMeshPrimitives();
	int total_poly_count  = 0;
	int total_loop_count  = 0;

	// collect edge_count and face_count from all parts
	for (int i = 0; i < prim_arr.getCount(); i++) {
		COLLADAFW::MeshPrimitive *mp = prim_arr[i];
		int type = mp->getPrimitiveType();
		switch (type) {
			case COLLADAFW::MeshPrimitive::TRIANGLES:
			case COLLADAFW::MeshPrimitive::TRIANGLE_FANS:
			case COLLADAFW::MeshPrimitive::POLYLIST:
			case COLLADAFW::MeshPrimitive::POLYGONS:
			{
				COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
				size_t prim_poly_count    = mpvc->getFaceCount();

				size_t prim_loop_count    = 0;
				for (int index=0; index < prim_poly_count; index++) {
					prim_loop_count += get_vertex_count(mpvc, index);
				}

				total_poly_count += prim_poly_count;
				total_loop_count += prim_loop_count;

				break;
			}
			default:
				break;
		}
	}

	// Add the data containers
	if (total_poly_count > 0) {
		me->totpoly = total_poly_count;
		me->totloop = total_loop_count;
		me->mpoly   = (MPoly *)CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, NULL, me->totpoly);
		me->mloop   = (MLoop *)CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CALLOC, NULL, me->totloop);

		unsigned int totuvset = collada_mesh->getUVCoords().getInputInfosArray().getCount();
		for (int i = 0; i < totuvset; i++) {
			if (collada_mesh->getUVCoords().getLength(i) == 0) {
				totuvset = 0;
				break;
			}
		}

		if (totuvset > 0) {
			for (int i = 0; i < totuvset; i++) {
				COLLADAFW::MeshVertexData::InputInfos *info = collada_mesh->getUVCoords().getInputInfosArray()[i];
				COLLADAFW::String &uvname = info->mName;
				// Allocate space for UV_data
				CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, uvname.c_str());
				CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, uvname.c_str());
			}
			// activate the first uv map
			me->mtpoly  = (MTexPoly *)CustomData_get_layer_n(&me->pdata, CD_MTEXPOLY, 0);
			me->mloopuv = (MLoopUV *) CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, 0);
		}

		int totcolset = collada_mesh->getColors().getInputInfosArray().getCount();
		if (totcolset > 0) {
			for (int i = 0; i < totcolset; i++) {
				COLLADAFW::MeshVertexData::InputInfos *info = collada_mesh->getColors().getInputInfosArray()[i];
				COLLADAFW::String colname = extract_vcolname(info->mName);
				CustomData_add_layer_named(&me->ldata,CD_MLOOPCOL,CD_DEFAULT,NULL,me->totloop, colname.c_str());
			}
			me->mloopcol = (MLoopCol *) CustomData_get_layer_n(&me->ldata, CD_MLOOPCOL, 0);
		}

	}
}