void	 LoaderFbxMesh::parseVertexColors(FbxMesh* mesh, int controlPointIndex, int vertexId)
{
	for(int i=0; i<mesh->GetElementVertexColorCount(); i++)
	{
		FbxGeometryElementVertexColor* vertexColorElement = mesh->GetElementVertexColor(i);
		FbxColor fbxColor;
		switch(vertexColorElement->GetMappingMode())
		{
		case FbxGeometryElement::eByControlPoint:
			fbxColor = parseVertexColorsByControlPoint(vertexColorElement, controlPointIndex);
			break;
		case FbxGeometryElement::eByPolygonVertex:
			fbxColor = parseVertexColorsByPolygonVertex(vertexColorElement, vertexId);
			break;
		default:
			break;
		}

		Float4 color;
		color.x = static_cast<float>(fbxColor.mRed);
		color.y = static_cast<float>(fbxColor.mGreen);
		color.z = static_cast<float>(fbxColor.mBlue);
		color.w = static_cast<float>(fbxColor.mAlpha);

		vertexColors_.push_back(color);
	}

}
Esempio n. 2
0
void FbxParser::ReadColor(FbxMesh* pMesh, int ctrlPointIndex,int vertexCounter , GS::float4& color)
{
	if (pMesh->GetElementVertexColorCount() < 1)
		return ; 
	FbxGeometryElementVertexColor* leVtxc = pMesh->GetElementVertexColor( 0);
	FbxColor fbxColor;		
	switch (leVtxc->GetMappingMode())
	{
	default:
		break;
	case FbxGeometryElement::eByControlPoint:
		switch (leVtxc->GetReferenceMode())
		{
		case FbxGeometryElement::eDirect:
			 fbxColor = leVtxc->GetDirectArray().GetAt(ctrlPointIndex);
			  color= GS::float4(fbxColor.mRed, fbxColor.mGreen, fbxColor.mBlue, fbxColor.mAlpha);
			break;
		case FbxGeometryElement::eIndexToDirect:
			{
				int id = leVtxc->GetIndexArray().GetAt(ctrlPointIndex);
				fbxColor = leVtxc->GetDirectArray().GetAt(id);
			     color= GS::float4(fbxColor.mRed, fbxColor.mGreen, fbxColor.mBlue, fbxColor.mAlpha);
			}
			break;
		default:
			break; // other reference modes not shown here!
		}
		break;

	case FbxGeometryElement::eByPolygonVertex:
		{
			switch (leVtxc->GetReferenceMode())
			{
			case FbxGeometryElement::eDirect:
				 fbxColor = leVtxc->GetDirectArray().GetAt(vertexCounter);
				 color= GS::float4(fbxColor.mRed, fbxColor.mGreen, fbxColor.mBlue, fbxColor.mAlpha);
				break;
			case FbxGeometryElement::eIndexToDirect:
				{
					int id = leVtxc->GetIndexArray().GetAt(vertexCounter);
					fbxColor = leVtxc->GetDirectArray().GetAt(id);
					color= GS::float4(fbxColor.mRed, fbxColor.mGreen, fbxColor.mBlue, fbxColor.mAlpha);
				}
				break;
			default:
				break; // other reference modes not shown here!
			}
		}
		break;

	case FbxGeometryElement::eByPolygon: // doesn't make much sense for UVs
	case FbxGeometryElement::eAllSame:   // doesn't make much sense for UVs
	case FbxGeometryElement::eNone:       // doesn't make much sense for UVs
		break;
	}

}
Esempio n. 3
0
//converts a FBX mesh to a CC mesh
static ccMesh* FromFbxMesh(FbxMesh* fbxMesh, bool alwaysDisplayLoadDialog/*=true*/, bool* coordinatesShiftEnabled/*=0*/, CCVector3d* coordinatesShift/*=0*/)
{
	if (!fbxMesh)
		return 0;

	int polyCount = fbxMesh->GetPolygonCount();
	//fbxMesh->GetLayer(
	unsigned triCount = 0;
	unsigned polyVertCount = 0; //different from vertCount (vertices can be counted multiple times here!)
	//as we can't load all polygons (yet ;) we already look if we can load any!
	{
		unsigned skipped = 0;
		for (int i=0; i<polyCount; ++i)
		{
			int pSize = fbxMesh->GetPolygonSize(i);

			if (pSize == 3)
			{
				++triCount;
				polyVertCount += 3;
			}
			else if (pSize == 4)
			{
				triCount += 2;
				polyVertCount += 4;
			}
			else
			{
				++skipped;
			}
		}

		if (triCount == 0)
		{
			ccLog::Warning(QString("[FBX] No triangle or quad found in mesh '%1'! (polygons with more than 4 vertices are not supported for the moment)").arg(fbxMesh->GetName()));
			return 0;
		}
		else if (skipped != 0)
		{
			ccLog::Warning(QString("[FBX] Some polygons in mesh '%1' were ignored (%2): polygons with more than 4 vertices are not supported for the moment)").arg(fbxMesh->GetName()).arg(skipped));
			return 0;
		}
	}

	int vertCount = fbxMesh->GetControlPointsCount();
	if (vertCount <= 0)
	{
		ccLog::Warning(QString("[FBX] Mesh '%1' has no vetex or no polygon?!").arg(fbxMesh->GetName()));
		return 0;
	}

	ccPointCloud* vertices = new ccPointCloud("vertices");
	ccMesh* mesh = new ccMesh(vertices);
	mesh->setName(fbxMesh->GetName());
	mesh->addChild(vertices);
	vertices->setEnabled(false);
	
	if (!mesh->reserve(static_cast<unsigned>(triCount)) || !vertices->reserve(vertCount))
	{
		ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1'!").arg(fbxMesh->GetName()));
		delete mesh;
		return 0;
	}

	//colors
	{
		for (int l=0; l<fbxMesh->GetElementVertexColorCount(); l++)
		{
			FbxGeometryElementVertexColor* vertColor = fbxMesh->GetElementVertexColor(l);
			//CC can only handle per-vertex colors
			if (vertColor->GetMappingMode() == FbxGeometryElement::eByControlPoint)
			{
				if (vertColor->GetReferenceMode() == FbxGeometryElement::eDirect
					|| vertColor->GetReferenceMode() == FbxGeometryElement::eIndexToDirect)
				{
					if (vertices->reserveTheRGBTable())
					{
						switch (vertColor->GetReferenceMode())
						{
						case FbxGeometryElement::eDirect:
							{
								for (int i=0; i<vertCount; ++i)
								{
									FbxColor c = vertColor->GetDirectArray().GetAt(i);
									vertices->addRGBColor(	static_cast<colorType>(c.mRed	* MAX_COLOR_COMP),
															static_cast<colorType>(c.mGreen	* MAX_COLOR_COMP),
															static_cast<colorType>(c.mBlue	* MAX_COLOR_COMP) );
								}
							}
							break;
						case FbxGeometryElement::eIndexToDirect:
							{
								for (int i=0; i<vertCount; ++i)
								{
									int id = vertColor->GetIndexArray().GetAt(i);
									FbxColor c = vertColor->GetDirectArray().GetAt(id);
									vertices->addRGBColor(	static_cast<colorType>(c.mRed	* MAX_COLOR_COMP),
															static_cast<colorType>(c.mGreen	* MAX_COLOR_COMP),
															static_cast<colorType>(c.mBlue	* MAX_COLOR_COMP) );
								}
							}
							break;
						default:
							assert(false);
							break;
						}

						vertices->showColors(true);
						mesh->showColors(true);
						break; //no need to look for other color fields (we won't be able to handle them!
					}
					else
					{
						ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' colors!").arg(fbxMesh->GetName()));
					}
				}
				else
				{
					ccLog::Warning(QString("[FBX] Color field #%i of mesh '%1' will be ignored (unhandled type)").arg(l).arg(fbxMesh->GetName()));
				}
			}
			else
			{
				ccLog::Warning(QString("[FBX] Color field #%i of mesh '%1' will be ignored (unhandled type)").arg(l).arg(fbxMesh->GetName()));
			}
		}
	}


	//normals can be per vertices or per-triangle
	int perPointNormals = -1;
	int perVertexNormals = -1;
	int perPolygonNormals = -1;
	{
        for (int j=0; j<fbxMesh->GetElementNormalCount(); j++)
        {
			FbxGeometryElementNormal* leNormals = fbxMesh->GetElementNormal(j);
			switch(leNormals->GetMappingMode())
			{
			case FbxGeometryElement::eByControlPoint:
				perPointNormals = j;
				break;
			case FbxGeometryElement::eByPolygonVertex:
				perVertexNormals = j;
				break;
			case FbxGeometryElement::eByPolygon:
				perPolygonNormals = j;
				break;
			default:
				//not handled
				break;
			}
		}
	}

	//per-point normals
	if (perPointNormals >= 0)
	{
		FbxGeometryElementNormal* leNormals = fbxMesh->GetElementNormal(perPointNormals);
		FbxLayerElement::EReferenceMode refMode = leNormals->GetReferenceMode();
		const FbxLayerElementArrayTemplate<FbxVector4>& normals = leNormals->GetDirectArray();
		assert(normals.GetCount() == vertCount);
		if (normals.GetCount() != vertCount)
		{
			ccLog::Warning(QString("[FBX] Wrong number of normals on mesh '%1'!").arg(fbxMesh->GetName()));
			perPointNormals = -1;
		}
		else if (!vertices->reserveTheNormsTable())
		{
			ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' normals!").arg(fbxMesh->GetName()));
			perPointNormals = -1;
		}
		else
		{
			//import normals
			for (int i=0; i<vertCount; ++i)
			{
				int id = refMode != FbxGeometryElement::eDirect ? leNormals->GetIndexArray().GetAt(i) : i;
				FbxVector4 N = normals.GetAt(id);
				//convert to CC-structure
				CCVector3 Npc(	static_cast<PointCoordinateType>(N.Buffer()[0]),
								static_cast<PointCoordinateType>(N.Buffer()[1]),
								static_cast<PointCoordinateType>(N.Buffer()[2]) );
				vertices->addNorm(Npc.u);
			}
			vertices->showNormals(true);
			mesh->showNormals(true);
			//no need to import the other normals (if any)
			perVertexNormals = -1;
			perPolygonNormals = -1;
		}
	}

	//per-triangle normals
	NormsIndexesTableType* normsTable = 0;
	if (perVertexNormals >= 0 || perPolygonNormals >= 0)
	{
		normsTable = new NormsIndexesTableType();
		if (!normsTable->reserve(polyVertCount) || !mesh->reservePerTriangleNormalIndexes())
		{
			ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' normals!").arg(fbxMesh->GetName()));
			normsTable->release();
			normsTable = 0;
		}
		else
		{
			mesh->setTriNormsTable(normsTable);
			mesh->addChild(normsTable);
			vertices->showNormals(true);
			mesh->showNormals(true);
		}
	}

	//import textures UV
	int perVertexUV = -1;
	bool hasTexUV = false;
	{
		for (int l=0; l<fbxMesh->GetElementUVCount(); ++l)
		{
			FbxGeometryElementUV* leUV = fbxMesh->GetElementUV(l);
			//per-point UV coordinates
			if (leUV->GetMappingMode() == FbxGeometryElement::eByControlPoint)
			{
				TextureCoordsContainer* vertTexUVTable = new TextureCoordsContainer();
				if (!vertTexUVTable->reserve(vertCount) || !mesh->reservePerTriangleTexCoordIndexes())
				{
					vertTexUVTable->release();
					ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' UV coordinates!").arg(fbxMesh->GetName()));
				}
				else
				{
					FbxLayerElement::EReferenceMode refMode = leUV->GetReferenceMode();
					for (int i=0; i<vertCount; ++i)
					{
						int id = refMode != FbxGeometryElement::eDirect ? leUV->GetIndexArray().GetAt(i) : i;
						FbxVector2 uv = leUV->GetDirectArray().GetAt(id);
						//convert to CC-structure
						float uvf[2] = {static_cast<float>(uv.Buffer()[0]),
										static_cast<float>(uv.Buffer()[1])};
						vertTexUVTable->addElement(uvf);
					}
					mesh->addChild(vertTexUVTable);
					hasTexUV = true;
				}
				perVertexUV = -1;
				break; //no need to look to the other UV fields (can't handle them!)
			}
			else if (leUV->GetMappingMode() == FbxGeometryElement::eByPolygonVertex)
			{
				//per-vertex UV coordinates
				perVertexUV = l;
			}
		}
	}

	//per-vertex UV coordinates
	TextureCoordsContainer* texUVTable = 0;
	if (perVertexUV >= 0)
	{
		texUVTable = new TextureCoordsContainer();
		if (!texUVTable->reserve(polyVertCount) || !mesh->reservePerTriangleTexCoordIndexes())
		{
			texUVTable->release();
			ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' UV coordinates!").arg(fbxMesh->GetName()));
		}
		else
		{
			mesh->addChild(texUVTable);
			hasTexUV = true;
		}
	}

	//import polygons
	{
		for (int i=0; i<polyCount; ++i)
		{
			int pSize = fbxMesh->GetPolygonSize(i);

			if (pSize > 4)
			{
				//not handled for the moment
				continue;
			}
			//we split quads into two triangles

			//vertex indices
			int i1 = fbxMesh->GetPolygonVertex(i, 0);
			int i2 = fbxMesh->GetPolygonVertex(i, 1);
			int i3 = fbxMesh->GetPolygonVertex(i, 2);
			mesh->addTriangle(i1,i2,i3);

			int i4 = -1;
			if (pSize == 4)
			{
				i4 = fbxMesh->GetPolygonVertex(i, 3);
				mesh->addTriangle(i1,i3,i4);
			}

			if (hasTexUV)
			{
				if (texUVTable)
				{
					assert(perVertexUV >= 0);

					int uvIndex = static_cast<int>(texUVTable->currentSize());
					for (int j=0; j<pSize; ++j)
					{
						int lTextureUVIndex = fbxMesh->GetTextureUVIndex(i, j);
						FbxGeometryElementUV* leUV = fbxMesh->GetElementUV(perVertexUV);
						FbxVector2 uv = leUV->GetDirectArray().GetAt(lTextureUVIndex);
						//convert to CC-structure
						float uvf[2] = {static_cast<float>(uv.Buffer()[0]),
										static_cast<float>(uv.Buffer()[1])};
						texUVTable->addElement(uvf);
					}
					mesh->addTriangleTexCoordIndexes(uvIndex,uvIndex+1,uvIndex+2);
					if (pSize == 4)
						mesh->addTriangleTexCoordIndexes(uvIndex,uvIndex+2,uvIndex+3);
				}
				else
				{
					mesh->addTriangleTexCoordIndexes(i1,i2,i3);
					if (pSize == 4)
						mesh->addTriangleTexCoordIndexes(i1,i3,i4);
				}
			}

			//per-triangle normals
			if (normsTable)
			{
				int nIndex = static_cast<int>(normsTable->currentSize());
				for (int j=0; j<pSize; ++j)
				{
					FbxVector4 N;
					fbxMesh->GetPolygonVertexNormal(i, j, N);
					CCVector3 Npc(	static_cast<PointCoordinateType>(N.Buffer()[0]),
									static_cast<PointCoordinateType>(N.Buffer()[1]),
									static_cast<PointCoordinateType>(N.Buffer()[2]) );
					normsTable->addElement(ccNormalVectors::GetNormIndex(Npc.u));
				}

				mesh->addTriangleNormalIndexes(nIndex,nIndex+1,nIndex+2);
				if (pSize == 4)
					mesh->addTriangleNormalIndexes(nIndex,nIndex+2,nIndex+3);
			}
		}
		
		if (mesh->size() == 0)
		{
			ccLog::Warning(QString("[FBX] No triangle found in mesh '%1'! (only triangles are supported for the moment)").arg(fbxMesh->GetName()));
			delete mesh;
			return 0;
		}
	}

	//import vertices
	{
		const FbxVector4* fbxVertices = fbxMesh->GetControlPoints();
		assert(vertices && fbxVertices);
		CCVector3d Pshift(0,0,0);
		for (int i=0; i<vertCount; ++i, ++fbxVertices)
		{
			const double* P = fbxVertices->Buffer();
			assert(P[3] == 0);

			//coordinate shift management
			if (i == 0)
			{
				bool shiftAlreadyEnabled = (coordinatesShiftEnabled && *coordinatesShiftEnabled && coordinatesShift);
				if (shiftAlreadyEnabled)
					Pshift = *coordinatesShift;
				bool applyAll = false;
				if (	sizeof(PointCoordinateType) < 8
					&&	ccCoordinatesShiftManager::Handle(P,0,alwaysDisplayLoadDialog,shiftAlreadyEnabled,Pshift,0,applyAll))
				{
					vertices->setGlobalShift(Pshift);
					ccLog::Warning("[FBX] Mesh has been recentered! Translation: (%.2f,%.2f,%.2f)",Pshift.x,Pshift.y,Pshift.z);

					//we save coordinates shift information
					if (applyAll && coordinatesShiftEnabled && coordinatesShift)
					{
						*coordinatesShiftEnabled = true;
						*coordinatesShift = Pshift;
					}
				}
			}

			CCVector3 PV(	static_cast<PointCoordinateType>(P[0] + Pshift.x),
							static_cast<PointCoordinateType>(P[1] + Pshift.y),
							static_cast<PointCoordinateType>(P[2] + Pshift.z) );

			vertices->addPoint(PV);
		}
	}

	//import textures
	{
		//TODO
	}

	return mesh;
}
Esempio n. 4
0
void loadVertexColor(FbxMesh* fbxMesh, int vertexIndex, int controlPointIndex, Vertex* vertex)
{
    if (fbxMesh->GetElementVertexColorCount() > 0)
    {
        // Get only the first vertex color.
        FbxGeometryElementVertexColor* vertexColor = fbxMesh->GetElementVertexColor(0);
        FbxGeometryElement::EMappingMode mappingMode = vertexColor->GetMappingMode();
        if (mappingMode == FbxGeometryElement::eByControlPoint)
        {
            switch (vertexColor->GetReferenceMode())
            {
            case FbxGeometryElement::eDirect:
                {
                    FbxColor color = vertexColor->GetDirectArray().GetAt(controlPointIndex);

                    vertex->hasDiffuse = true;
                    vertex->diffuse.x = (float)color.mRed;
                    vertex->diffuse.y = (float)color.mGreen;
                    vertex->diffuse.z = (float)color.mBlue;
                    vertex->diffuse.w = (float)color.mAlpha;
                }
                break;
            case FbxGeometryElement::eIndexToDirect:
                {
                    int id = vertexColor->GetIndexArray().GetAt(controlPointIndex);
                    FbxColor color = vertexColor->GetDirectArray().GetAt(id);

                    vertex->hasDiffuse = true;
                    vertex->diffuse.x = (float)color.mRed;
                    vertex->diffuse.y = (float)color.mGreen;
                    vertex->diffuse.z = (float)color.mBlue;
                    vertex->diffuse.w = (float)color.mAlpha;
                }
                break;
            default:
                break;
            }
        }
        else if (mappingMode == FbxGeometryElement::eByPolygonVertex)
        {
            switch (vertexColor->GetReferenceMode())
            {
            case FbxGeometryElement::eDirect:
                {
                    FbxColor color = vertexColor->GetDirectArray().GetAt(vertexIndex);

                    vertex->hasDiffuse = true;
                    vertex->diffuse.x = (float)color.mRed;
                    vertex->diffuse.y = (float)color.mGreen;
                    vertex->diffuse.z = (float)color.mBlue;
                    vertex->diffuse.w = (float)color.mAlpha;
                }
                break;
            case FbxGeometryElement::eIndexToDirect:
                {
                    int id = vertexColor->GetIndexArray().GetAt(vertexIndex);
                    FbxColor color = vertexColor->GetDirectArray().GetAt(id);

                    vertex->hasDiffuse = true;
                    vertex->diffuse.x = (float)color.mRed;
                    vertex->diffuse.y = (float)color.mGreen;
                    vertex->diffuse.z = (float)color.mBlue;
                    vertex->diffuse.w = (float)color.mAlpha;
                }
                break;
            default:
                break;
            }
        }
    }
}
Esempio n. 5
0
void fbxLoader2::readColor(FbxMesh* mesh, int controlPointIndex, int vertexCounter, D3DXVECTOR4* color)
{
	if(mesh->GetElementVertexColorCount()<1)
	{
		return;
	}

	FbxGeometryElementVertexColor* vertexColor = mesh->GetElementVertexColor(0);
	switch(vertexColor->GetMappingMode())
	{
	case FbxGeometryElement::eByControlPoint:
		{
			switch(vertexColor->GetReferenceMode())
			{
			case FbxGeometryElement::eDirect:
				{
					color->x = (float)vertexColor->GetDirectArray().GetAt(controlPointIndex).mRed;
					color->y = (float)vertexColor->GetDirectArray().GetAt(controlPointIndex).mGreen;
					color->z = (float)vertexColor->GetDirectArray().GetAt(controlPointIndex).mBlue;
					color->w = (float)vertexColor->GetDirectArray().GetAt(controlPointIndex).mAlpha;
				}
				break;
			
			case FbxGeometryElement::eIndexToDirect:
				{
					int id = vertexColor->GetIndexArray().GetAt(controlPointIndex);
					color->x = (float)vertexColor->GetDirectArray().GetAt(id).mRed;
					color->y = (float)vertexColor->GetDirectArray().GetAt(id).mGreen;
					color->z = (float)vertexColor->GetDirectArray().GetAt(id).mBlue;
					color->w = (float)vertexColor->GetDirectArray().GetAt(id).mAlpha;
				}
				break;
				
			default:
				break;
			}
		}
		break;

	case FbxGeometryElement::eByPolygonVertex:
		{
			switch(vertexColor->GetReferenceMode())
			{
			case FbxGeometryElement::eDirect:
				{
					color->x = (float)vertexColor->GetDirectArray().GetAt(vertexCounter).mRed;
					color->y = (float)vertexColor->GetDirectArray().GetAt(vertexCounter).mGreen;
					color->z = (float)vertexColor->GetDirectArray().GetAt(vertexCounter).mBlue;
					color->w = (float)vertexColor->GetDirectArray().GetAt(vertexCounter).mAlpha;
				}
				break;
			case FbxGeometryElement::eIndexToDirect:
				{
					int id = vertexColor->GetIndexArray().GetAt(vertexCounter);
					color->x = (float)vertexColor->GetDirectArray().GetAt(id).mRed;
					color->y = (float)vertexColor->GetDirectArray().GetAt(id).mGreen;
					color->z = (float)vertexColor->GetDirectArray().GetAt(id).mBlue;
					color->w = (float)vertexColor->GetDirectArray().GetAt(id).mAlpha;
				}
				break;
			default:
				break;
			}
		}
		break;
	}
}
Esempio n. 6
0
//converts a FBX mesh to a CC mesh
static ccMesh* FromFbxMesh(FbxMesh* fbxMesh, FileIOFilter::LoadParameters& parameters)
{
	if (!fbxMesh)
		return 0;

	int polyCount = fbxMesh->GetPolygonCount();
	//fbxMesh->GetLayer(
	unsigned triCount = 0;
	unsigned polyVertCount = 0; //different from vertCount (vertices can be counted multiple times here!)
	//as we can't load all polygons (yet ;) we already look if we can load any!
	{
		unsigned skipped = 0;
		for (int i=0; i<polyCount; ++i)
		{
			int pSize = fbxMesh->GetPolygonSize(i);

			if (pSize == 3)
			{
				++triCount;
				polyVertCount += 3;
			}
			else if (pSize == 4)
			{
				triCount += 2;
				polyVertCount += 4;
			}
			else
			{
				++skipped;
			}
		}

		if (triCount == 0)
		{
			ccLog::Warning(QString("[FBX] No triangle or quad found in mesh '%1'! (polygons with more than 4 vertices are not supported for the moment)").arg(fbxMesh->GetName()));
			return 0;
		}
		else if (skipped != 0)
		{
			ccLog::Warning(QString("[FBX] Some polygons in mesh '%1' were ignored (%2): polygons with more than 4 vertices are not supported for the moment)").arg(fbxMesh->GetName()).arg(skipped));
			return 0;
		}
	}

	int vertCount = fbxMesh->GetControlPointsCount();
	if (vertCount <= 0)
	{
		ccLog::Warning(QString("[FBX] Mesh '%1' has no vetex or no polygon?!").arg(fbxMesh->GetName()));
		return 0;
	}

	ccPointCloud* vertices = new ccPointCloud("vertices");
	ccMesh* mesh = new ccMesh(vertices);
	mesh->setName(fbxMesh->GetName());
	mesh->addChild(vertices);
	vertices->setEnabled(false);
	
	if (!mesh->reserve(static_cast<unsigned>(triCount)) || !vertices->reserve(vertCount))
	{
		ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1'!").arg(fbxMesh->GetName()));
		delete mesh;
		return 0;
	}

	//colors
	{
		for (int l=0; l<fbxMesh->GetElementVertexColorCount(); l++)
		{
			FbxGeometryElementVertexColor* vertColor = fbxMesh->GetElementVertexColor(l);
			//CC can only handle per-vertex colors
			if (vertColor->GetMappingMode() == FbxGeometryElement::eByControlPoint)
			{
				if (vertColor->GetReferenceMode() == FbxGeometryElement::eDirect
					|| vertColor->GetReferenceMode() == FbxGeometryElement::eIndexToDirect)
				{
					if (vertices->reserveTheRGBTable())
					{
						switch (vertColor->GetReferenceMode())
						{
						case FbxGeometryElement::eDirect:
							{
								for (int i=0; i<vertCount; ++i)
								{
									FbxColor c = vertColor->GetDirectArray().GetAt(i);
									vertices->addRGBColor(	static_cast<colorType>(c.mRed	* ccColor::MAX),
															static_cast<colorType>(c.mGreen	* ccColor::MAX),
															static_cast<colorType>(c.mBlue	* ccColor::MAX) );
								}
							}
							break;
						case FbxGeometryElement::eIndexToDirect:
							{
								for (int i=0; i<vertCount; ++i)
								{
									int id = vertColor->GetIndexArray().GetAt(i);
									FbxColor c = vertColor->GetDirectArray().GetAt(id);
									vertices->addRGBColor(	static_cast<colorType>(c.mRed	* ccColor::MAX),
															static_cast<colorType>(c.mGreen	* ccColor::MAX),
															static_cast<colorType>(c.mBlue	* ccColor::MAX) );
								}
							}
							break;
						default:
							assert(false);
							break;
						}

						vertices->showColors(true);
						mesh->showColors(true);
						break; //no need to look for other color fields (we won't be able to handle them!
					}
					else
					{
						ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' colors!").arg(fbxMesh->GetName()));
					}
				}
				else
				{
					ccLog::Warning(QString("[FBX] Color field #%i of mesh '%1' will be ignored (unhandled type)").arg(l).arg(fbxMesh->GetName()));
				}
			}
			else
			{
				ccLog::Warning(QString("[FBX] Color field #%i of mesh '%1' will be ignored (unhandled type)").arg(l).arg(fbxMesh->GetName()));
			}
		}
	}

	//normals can be per vertices or per-triangle
	int perPointNormals = -1;
	int perVertexNormals = -1;
	int perPolygonNormals = -1;
	{
		for (int j=0; j<fbxMesh->GetElementNormalCount(); j++)
		{
			FbxGeometryElementNormal* leNormals = fbxMesh->GetElementNormal(j);
			switch(leNormals->GetMappingMode())
			{
			case FbxGeometryElement::eByControlPoint:
				perPointNormals = j;
				break;
			case FbxGeometryElement::eByPolygonVertex:
				perVertexNormals = j;
				break;
			case FbxGeometryElement::eByPolygon:
				perPolygonNormals = j;
				break;
			default:
				//not handled
				break;
			}
		}
	}

	//per-point normals
	if (perPointNormals >= 0)
	{
		FbxGeometryElementNormal* leNormals = fbxMesh->GetElementNormal(perPointNormals);
		FbxLayerElement::EReferenceMode refMode = leNormals->GetReferenceMode();
		const FbxLayerElementArrayTemplate<FbxVector4>& normals = leNormals->GetDirectArray();
		assert(normals.GetCount() == vertCount);
		if (normals.GetCount() != vertCount)
		{
			ccLog::Warning(QString("[FBX] Wrong number of normals on mesh '%1'!").arg(fbxMesh->GetName()));
			perPointNormals = -1;
		}
		else if (!vertices->reserveTheNormsTable())
		{
			ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' normals!").arg(fbxMesh->GetName()));
			perPointNormals = -1;
		}
		else
		{
			//import normals
			for (int i=0; i<vertCount; ++i)
			{
				int id = refMode != FbxGeometryElement::eDirect ? leNormals->GetIndexArray().GetAt(i) : i;
				FbxVector4 N = normals.GetAt(id);
				//convert to CC-structure
				CCVector3 Npc(	static_cast<PointCoordinateType>(N.Buffer()[0]),
								static_cast<PointCoordinateType>(N.Buffer()[1]),
								static_cast<PointCoordinateType>(N.Buffer()[2]) );
				vertices->addNorm(Npc);
			}
			vertices->showNormals(true);
			mesh->showNormals(true);
			//no need to import the other normals (if any)
			perVertexNormals = -1;
			perPolygonNormals = -1;
		}
	}

	//per-triangle normals
	NormsIndexesTableType* normsTable = 0;
	if (perVertexNormals >= 0 || perPolygonNormals >= 0)
	{
		normsTable = new NormsIndexesTableType();
		if (!normsTable->reserve(polyVertCount) || !mesh->reservePerTriangleNormalIndexes())
		{
			ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' normals!").arg(fbxMesh->GetName()));
			normsTable->release();
			normsTable = 0;
		}
		else
		{
			mesh->setTriNormsTable(normsTable);
			vertices->showNormals(true);
			mesh->showNormals(true);
		}
	}

	//materials
	ccMaterialSet* materials = 0;
	{
		FbxNode* lNode = fbxMesh->GetNode();
		int lMaterialCount = lNode ? lNode->GetMaterialCount() : 0;
		for (int i=0; i<lMaterialCount; i++)
		{
			FbxSurfaceMaterial *lBaseMaterial = lNode->GetMaterial(i);

			bool isLambert = lBaseMaterial->GetClassId().Is(FbxSurfaceLambert::ClassId);
			bool isPhong = lBaseMaterial->GetClassId().Is(FbxSurfacePhong::ClassId);
			if (isLambert || isPhong)
			{
				ccMaterial::Shared mat(new ccMaterial(lBaseMaterial->GetName()));

				FbxSurfaceLambert* lLambertMat = static_cast<FbxSurfaceLambert*>(lBaseMaterial);
			
				float ambient[4];
				float diffuse[4];
				float emission[4];
				float specular[4];

				FbxSurfacePhong* lPhongMat = isPhong ? static_cast<FbxSurfacePhong*>(lBaseMaterial) : 0;

				for (int k=0; k<3; ++k)
				{
					ambient[k]  = static_cast<float>(lLambertMat->Ambient.Get()[k]);
					diffuse[k]  = static_cast<float>(lLambertMat->Diffuse.Get()[k]);
					emission[k] = static_cast<float>(lLambertMat->Emissive.Get()[k]);

					if (lPhongMat)
					{
						specular[k]		= static_cast<float>(lPhongMat->Specular.Get()[k]);
					}
				}

				mat->setAmbient(ambient);
				mat->setDiffuse(diffuse);
				mat->setEmission(emission);
				if (isPhong)
				{
					mat->setSpecular(specular);
					assert(lPhongMat);
					mat->setShininess(static_cast<float>(lPhongMat->Shininess));
				}

				//import associated texture (if any)
				{
					int lTextureIndex;
					FBXSDK_FOR_EACH_TEXTURE(lTextureIndex)
					{
						FbxProperty lProperty = lBaseMaterial->FindProperty(FbxLayerElement::sTextureChannelNames[lTextureIndex]);
						if( lProperty.IsValid() )
						{
							int lTextureCount = lProperty.GetSrcObjectCount<FbxTexture>();
							FbxTexture* texture = 0; //we can handle only one texture per material! We'll take the non layered one by default (if any)
							for (int j = 0; j < lTextureCount; ++j)
							{
								//Here we have to check if it's layeredtextures, or just textures:
								FbxLayeredTexture *lLayeredTexture = lProperty.GetSrcObject<FbxLayeredTexture>(j);
								if (lLayeredTexture)
								{
									//we don't handle layered textures!
									/*int lNbTextures = lLayeredTexture->GetSrcObjectCount<FbxTexture>();
									for (int k=0; k<lNbTextures; ++k)
									{
										FbxTexture* lTexture = lLayeredTexture->GetSrcObject<FbxTexture>(k);
										if(lTexture)
										{
										}
									}
									//*/
								}
								else
								{
									//non-layered texture
									FbxTexture* lTexture = lProperty.GetSrcObject<FbxTexture>(j);
									if(lTexture)
									{
										//we take the first non layered texture by default
										texture = lTexture;
										break;
									}
								}
							}

							if (texture)
							{
								FbxFileTexture *lFileTexture = FbxCast<FbxFileTexture>(texture);
								if (lFileTexture)
								{
									const char* texAbsoluteFilename = lFileTexture->GetFileName();
									ccLog::PrintDebug(QString("[FBX] Texture absolue filename: %1").arg(texAbsoluteFilename));
									if (texAbsoluteFilename != 0 && texAbsoluteFilename[0] != 0)
									{
										if (!mat->loadAndSetTexture(texAbsoluteFilename))
										{
											ccLog::Warning(QString("[FBX] Failed to load texture file: %1").arg(texAbsoluteFilename));
										}
									}
								}
							}
						}
					}
				}

				if (!materials)
				{
					materials = new ccMaterialSet("materials");
					mesh->addChild(materials);
				}
				materials->addMaterial(mat);
			}
			else
			{
				ccLog::Warning(QString("[FBX] Material '%1' has an unhandled type").arg(lBaseMaterial->GetName()));
			}
		}
Esempio n. 7
0
	Submesh *FBX::buildSubmeshFromFBX(FbxMesh *lMesh, int material_index, bool single_material) {
		int lPolygonCount=lMesh->GetPolygonCount();
		FbxLayerElementArrayTemplate<int>* lMaterialIndice = NULL;

		bool add=false;

		if (!single_material) {
			FbxGeometryElement::EMappingMode lMaterialMappingMode = FbxGeometryElement::eNone;
			if (lMesh->GetElementMaterial()) {
				lMaterialIndice = &lMesh->GetElementMaterial()->GetIndexArray();
				lMaterialMappingMode = lMesh->GetElementMaterial()->GetMappingMode();

				if (!lMaterialIndice) printf("Mesh has no material index element.\n");

				if (lMaterialIndice && lMaterialMappingMode == FbxGeometryElement::eByPolygon) {
					if (lMaterialIndice->GetCount() == lPolygonCount) {
						add = true;
					}
				}
			}
		}
		else add = true;
	
		if (add) {
			vector<Vertex *> new_vertices;
			vector<Vector3> new_faces;

			int control_points_count=lMesh->GetControlPointsCount();
			FbxVector4 *control_points=lMesh->GetControlPoints();

			int vertex_index = 0;
			for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex) {
				if (lMaterialIndice) {
					const int lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex);
					if (lMaterialIndex != material_index) continue;
				}

				int polygon_size=lMesh->GetPolygonSize(lPolygonIndex);
				if (polygon_size == 3) {
					Vector3 face;

					for (int j=0; j<polygon_size; j++) {
						Vertex *vertex=new Vertex();

						int control_point_index=lMesh->GetPolygonVertex(lPolygonIndex, j);
						FbxVector4 control_point=control_points[control_point_index];
						vertex->setPosition(Vector3(control_point[0], control_point[2], -control_point[1]));

						// Get Normal for Vertex
						FbxVector4 normal;
						lMesh->GetPolygonVertexNormal(lPolygonIndex, j, normal);
						vertex->setNormal(Vector3(normal[0], normal[2], -normal[1]));

						// Get UVs for Vertex
						FbxStringList uv_sets;
						lMesh->GetUVSetNames(uv_sets);
						for (int set=0; set<uv_sets.GetCount(); set++) {
							if (set >= 4) break;
							FbxVector2 uv;
							bool no_uv;
							lMesh->GetPolygonVertexUV(lPolygonIndex, j, uv_sets[set].Buffer(), uv, no_uv);
							vertex->setUV(Vector2(uv[0], 1.0 - uv[1]), set);
						}

						// Get Vertex Color for Vertex
						FbxColor vtx_c(1.0, 1.0, 1.0, 1.0);
						for (int l = 0; l < lMesh->GetElementVertexColorCount(); l++) {
							FbxGeometryElementVertexColor* leVtxc = lMesh->GetElementVertexColor(l);

							if (leVtxc->GetMappingMode() == FbxGeometryElement::eByControlPoint) {
								if (leVtxc->GetReferenceMode() == FbxGeometryElement::eDirect) {
									vtx_c = leVtxc->GetDirectArray().GetAt(control_point_index);
								}
								else if (leVtxc->GetReferenceMode() == FbxGeometryElement::eIndexToDirect) {
									int id = leVtxc->GetIndexArray().GetAt(control_point_index);
									vtx_c = leVtxc->GetDirectArray().GetAt(id);
								}
							}
							else if (leVtxc->GetMappingMode() == FbxGeometryElement::eByPolygonVertex) {
								if (leVtxc->GetReferenceMode() == FbxGeometryElement::eDirect) {
									vtx_c = leVtxc->GetDirectArray().GetAt(vertex_index);
								}
								else if (leVtxc->GetReferenceMode() == FbxGeometryElement::eIndexToDirect) {
									int id = leVtxc->GetIndexArray().GetAt(vertex_index);
									vtx_c = leVtxc->GetDirectArray().GetAt(id);
								}
							}
						}

						vertex->setColor(Color(vtx_c.mRed, vtx_c.mGreen, vtx_c.mBlue, vtx_c.mAlpha));
						
						if (j == 0) face.x=new_vertices.size();
						if (j == 1) face.y=new_vertices.size();
						if (j == 2) face.z=new_vertices.size();

						new_vertices.push_back(vertex);
						vertex_index++;
					}
					new_faces.push_back(face);
					
				}
				else printf("Unsupported polygon size %d.\n", polygon_size);
			}

			printf("Building submesh with %d vertices and %d faces\n", new_vertices.size(), new_faces.size());

			if ((new_vertices.size() >= 3) && new_faces.size()) {
				Submesh *submesh=new Submesh();
				submesh->build(new_vertices, new_faces);
				submesh->addBone(0);

				VertexFormat *vertex_format=new VertexFormat(LIBGENS_VERTEX_FORMAT_PC);
				submesh->setVertexFormat(vertex_format);
				return submesh;
			}
		}

		return NULL;
	}
Esempio n. 8
0
//--------------------------------------------------------------------------
void SaveMesh(FbxNode* pNode, const VeDirectoryPtr& spDest) noexcept
{
	Mesh kMesh;
	FbxMesh* pMesh = (FbxMesh*)pNode->GetNodeAttribute();
	
	kMesh.m_kName = pNode->GetName();
	kMesh.m_stFaces = pMesh->GetPolygonCount();
	kMesh.m_stVerts = kMesh.m_stFaces * 3;

	kMesh.m_kIndices.resize(kMesh.m_stVerts);
	kMesh.m_kPosition.resize(kMesh.m_stVerts);

	kMesh.m_kNormals.resize(pMesh->GetElementNormalCount());
	for (auto& v : kMesh.m_kNormals)
	{
		v.resize(kMesh.m_stVerts);
	}
	kMesh.m_kTexcoords.resize(pMesh->GetElementUVCount());
	for (auto& v : kMesh.m_kTexcoords)
	{
		v.resize(kMesh.m_stVerts);
	}
	kMesh.m_kColors.resize(pMesh->GetElementVertexColorCount());
	for (auto& v : kMesh.m_kColors)
	{
		v.resize(kMesh.m_stVerts);
	}	

	int element_mat = -1;
	for (int i(0); i < pMesh->GetElementMaterialCount(); ++i)
	{
		FbxGeometryElementMaterial* lMaterialElement = pMesh->GetElementMaterial(i);
		if (lMaterialElement->GetMappingMode() == FbxGeometryElement::eByPolygon)
		{
			element_mat = i;
			break;
		}
	}
	if (element_mat >= 0)
	{
		kMesh.m_kAttributes.resize(kMesh.m_stFaces);
	}

	FbxVector4* lControlPoints = pMesh->GetControlPoints();
	for (int i(0); i < (int)(kMesh.m_stFaces); ++i)
	{
		int lPolygonSize = pMesh->GetPolygonSize(i);
		VE_ASSERT_ALWAYS(lPolygonSize == 3);
		for (int j(0); j < lPolygonSize; ++j)
		{
			uint32_t u32Index = i * 3 + j;
			kMesh.m_kIndices[u32Index] = u32Index;
			int lControlPointIndex = pMesh->GetPolygonVertex(i, j);
			auto& pos = kMesh.m_kPosition[u32Index];
			pos.x = (float)lControlPoints[lControlPointIndex][0];
			pos.y = (float)lControlPoints[lControlPointIndex][1];
			pos.z = (float)lControlPoints[lControlPointIndex][2];
			
			for (int k(0); k < (int)(kMesh.m_kColors.size()); ++k)
			{
				FbxColor c;
				FbxGeometryElementVertexColor* leVtxc = pMesh->GetElementVertexColor(k);
				switch (leVtxc->GetMappingMode())
				{
				default:
					break;
				case FbxGeometryElement::eByControlPoint:
					switch (leVtxc->GetReferenceMode())
					{
					case FbxGeometryElement::eDirect:
						c = leVtxc->GetDirectArray().GetAt(lControlPointIndex);
						break;
					case FbxGeometryElement::eIndexToDirect:
					{
						int id = leVtxc->GetIndexArray().GetAt(lControlPointIndex);
						c = leVtxc->GetDirectArray().GetAt(id);
					}
					break;
					default:
						break; // other reference modes not shown here!
					}
					break;

				case FbxGeometryElement::eByPolygonVertex:
				{
					switch (leVtxc->GetReferenceMode())
					{
					case FbxGeometryElement::eDirect:
						c = leVtxc->GetDirectArray().GetAt(u32Index);
						break;
					case FbxGeometryElement::eIndexToDirect:
					{
						int id = leVtxc->GetIndexArray().GetAt(u32Index);
						c = leVtxc->GetDirectArray().GetAt(id);
					}
					break;
					default:
						break; // other reference modes not shown here!
					}
				}
				break;
				case FbxGeometryElement::eByPolygon: // doesn't make much sense for UVs
				case FbxGeometryElement::eAllSame:   // doesn't make much sense for UVs
				case FbxGeometryElement::eNone:       // doesn't make much sense for UVs
					break;
				}
				auto& color = kMesh.m_kColors[k][u32Index];
				color.x = (float)c[0];
				color.y = (float)c[1];
				color.z = (float)c[2];
				color.w = (float)c[3];
			}

			for (int k(0); k < (int)(kMesh.m_kTexcoords.size()); ++k)
			{
				FbxVector2 uv;
				FbxGeometryElementUV* leUV = pMesh->GetElementUV(k);
				switch (leUV->GetMappingMode())
				{
				default:
					break;
				case FbxGeometryElement::eByControlPoint:
					switch (leUV->GetReferenceMode())
					{
					case FbxGeometryElement::eDirect:
						uv = leUV->GetDirectArray().GetAt(lControlPointIndex);
						break;
					case FbxGeometryElement::eIndexToDirect:
					{
						int id = leUV->GetIndexArray().GetAt(lControlPointIndex);
						uv = leUV->GetDirectArray().GetAt(id);
					}
					break;
					default:
						break; // other reference modes not shown here!
					}
					break;

				case FbxGeometryElement::eByPolygonVertex:
				{
					int lTextureUVIndex = pMesh->GetTextureUVIndex(i, j);
					switch (leUV->GetReferenceMode())
					{
					case FbxGeometryElement::eDirect:
					case FbxGeometryElement::eIndexToDirect:
					{
						uv = leUV->GetDirectArray().GetAt(lTextureUVIndex);
					}
					break;
					default:
						break; // other reference modes not shown here!
					}
				}
				break;

				case FbxGeometryElement::eByPolygon: // doesn't make much sense for UVs
				case FbxGeometryElement::eAllSame:   // doesn't make much sense for UVs
				case FbxGeometryElement::eNone:       // doesn't make much sense for UVs
					break;
				}

				auto& texcoord = kMesh.m_kTexcoords[k][u32Index];
				texcoord.x = (float)uv[0];
				texcoord.y = (float)uv[1];
			}
			
			for (int k(0); k < (int)(kMesh.m_kNormals.size()); ++k)
			{
				FbxVector4 n;
				FbxGeometryElementNormal* leNormal = pMesh->GetElementNormal(k);
				if (leNormal->GetMappingMode() == FbxGeometryElement::eByPolygonVertex)
				{
					switch (leNormal->GetReferenceMode())
					{
					case FbxGeometryElement::eDirect:
						n = leNormal->GetDirectArray().GetAt(u32Index);
						break;
					case FbxGeometryElement::eIndexToDirect:
					{
						int id = leNormal->GetIndexArray().GetAt(u32Index);
						n = leNormal->GetDirectArray().GetAt(id);
					}
					break;
					default:
						break; // other reference modes not shown here!
					}
				}

				auto& normal = kMesh.m_kNormals[k][u32Index];
				normal.x = (float)n[0];
				normal.y = (float)n[1];
				normal.z = (float)n[2];
			}

			if (element_mat >= 0)
			{
				FbxGeometryElementMaterial* lMaterialElement = pMesh->GetElementMaterial(element_mat);
				FbxSurfaceMaterial* lMaterial = NULL;
				int lMatId = -1;
				lMaterial = pMesh->GetNode()->GetMaterial(lMaterialElement->GetIndexArray().GetAt(i));
				lMatId = lMaterialElement->GetIndexArray().GetAt(i);
				kMesh.m_kAttributes[i] = lMatId;
			}
		}
	}
	kMesh.Process();
	kMesh.Save(spDest);
}
Esempio n. 9
0
void ReadColor(FbxMesh* pMesh , int ctrlPointIndex , int vertexCounter , D3DXVECTOR4* pColor)  
{  
	if(pMesh->GetElementVertexColorCount() < 1)  
	{  
		return;  
	}  

	FbxGeometryElementVertexColor* pVertexColor = pMesh->GetElementVertexColor(0);  
	switch(pVertexColor->GetMappingMode())  
	{  
	case FbxGeometryElement::eByControlPoint:  
		{  
			switch(pVertexColor->GetReferenceMode())  
			{  
			case FbxGeometryElement::eDirect:  
				{  
					pColor->x = pVertexColor->GetDirectArray().GetAt(ctrlPointIndex).mRed;  
					pColor->y = pVertexColor->GetDirectArray().GetAt(ctrlPointIndex).mGreen;  
					pColor->z = pVertexColor->GetDirectArray().GetAt(ctrlPointIndex).mBlue;  
					pColor->w = pVertexColor->GetDirectArray().GetAt(ctrlPointIndex).mAlpha;  
				}  
				break;  

			case FbxGeometryElement::eIndexToDirect:  
				{  
					int id = pVertexColor->GetIndexArray().GetAt(ctrlPointIndex);  
					pColor->x = pVertexColor->GetDirectArray().GetAt(id).mRed;  
					pColor->y = pVertexColor->GetDirectArray().GetAt(id).mGreen;  
					pColor->z = pVertexColor->GetDirectArray().GetAt(id).mBlue;  
					pColor->w = pVertexColor->GetDirectArray().GetAt(id).mAlpha;  
				}  
				break;  

			default:  
				break;  
			}  
		}  
		break;  

	case FbxGeometryElement::eByPolygonVertex:  
		{  
			switch (pVertexColor->GetReferenceMode())  
			{  
			case FbxGeometryElement::eDirect:  
				{  
					pColor->x = pVertexColor->GetDirectArray().GetAt(vertexCounter).mRed;  
					pColor->y = pVertexColor->GetDirectArray().GetAt(vertexCounter).mGreen;  
					pColor->z = pVertexColor->GetDirectArray().GetAt(vertexCounter).mBlue;  
					pColor->w = pVertexColor->GetDirectArray().GetAt(vertexCounter).mAlpha;  
				}  
				break;  
			case FbxGeometryElement::eIndexToDirect:  
				{  
					int id = pVertexColor->GetIndexArray().GetAt(vertexCounter);  
					pColor->x = pVertexColor->GetDirectArray().GetAt(id).mRed;  
					pColor->y = pVertexColor->GetDirectArray().GetAt(id).mGreen;  
					pColor->z = pVertexColor->GetDirectArray().GetAt(id).mBlue;  
					pColor->w = pVertexColor->GetDirectArray().GetAt(id).mAlpha;  
				}  
				break;  
			default:  
				break;  
			}  
		}  
		break;  
	}  
}