Example #1
0
void Utilities::PrintMatrix(FbxMatrix& inMatrix)
{
	FbxString lMatrixValue;
	for (int k = 0; k<4; ++k)
	{
		FbxVector4 lRow = inMatrix.GetRow(k);
		char        lRowValue[1024];

		FBXSDK_sprintf(lRowValue, 1024, "%9.4f %9.4f %9.4f %9.4f\n", lRow[0], lRow[1], lRow[2], lRow[3]);
		lMatrixValue += FbxString("        ") + FbxString(lRowValue);
	}

	std::cout << lMatrixValue.Buffer();
}
Example #2
0
bool gltfPackage::LoadScene (const std::string &fn) {
	auto pMgr =fbxSdkMgr::Instance ()->fbxMgr () ;
	FbxAutoDestroyPtr<FbxImporter> pImporter (FbxImporter::Create (pMgr, "")) ;

	if ( !pImporter->Initialize ((fn).c_str (), -1, pMgr->GetIOSettings ()) )
		return (false) ;
	if ( pImporter->IsFBX () ) {
		// From this point, it is possible to access animation stack information without
		// the expense of loading the entire file.

		// Set the import states. By default, the import states are always set to true.
	}

	bool bStatus =pImporter->Import (_scene) ;
	if ( _ioSettings._name.length () )
		_scene->SetName ((_ioSettings._name).c_str ()) ;
	else if ( _scene->GetName () == FbxString ("") )
		//_scene->SetName ("untitled") ;
		_scene->SetName ((gltfPackage::filename (fn)).c_str ()) ;

	//if ( bStatus == false && pImporter->GetStatus ().GetCode () == FbxStatus::ePasswordError ) {
	//}

	// Get current UpAxis of the FBX file.
	// This have to be done before ConvertiAxisSystem(), cause the function will always change SceneAxisSystem to Y-up.
	// First, however, if we have the ForcedFileAxis activated, we need to overwrite the global settings.
	//switch ( IOS_REF.GetEnumProp (IMP_FILE_UP_AXIS, FbxMayaUtility::eUPAXIS_AUTO) ) {
	//	default:
	//	case FbxMayaUtility::eUPAXIS_AUTO:
	//		break ;
	//	case FbxMayaUtility::eUPAXIS_Y:
	//		_scene->GetGlobalSettings ().SetAxisSystem (FbxAxisSystem::MayaYUp) ;
	//		break ;
	//	case FbxMayaUtility::eUPAXIS_Z:
	//		_scene->GetGlobalSettings ().SetAxisSystem (FbxAxisSystem::MayaZUp) ;
	//	break ;
	//}
	//FbxAxisSystem sceneAxisSystem =_scene->GetGlobalSettings ().GetAxisSystem () ;
	//int lSign =0 ;
	//FbxAxisSystem::EUpVector upVectorFromFile =sceneAxisSystem.GetUpVector (lSign) ;

	FbxAxisSystem::MayaYUp.ConvertScene (_scene) ; // We want the Y up axis for glTF

	FbxSystemUnit sceneSystemUnit =_scene->GetGlobalSettings ().GetSystemUnit () ; // We want meter as default unit for gltTF
	if ( sceneSystemUnit != FbxSystemUnit::m ) {
		//const FbxSystemUnit::ConversionOptions conversionOptions ={
		//	false, // mConvertRrsNodes
		//	true, // mConvertAllLimits
		//	true, // mConvertClusters
		//	false, // mConvertLightIntensity
		//	true, // mConvertPhotometricLProperties
		//	false  // mConvertCameraClipPlanes
		//} ;
		//FbxSystemUnit::m.ConvertScene (_scene, conversionOptions) ;
		FbxSystemUnit::m.ConvertScene (_scene) ;
	}

	FbxGeometryConverter converter (fbxSdkMgr::Instance ()->fbxMgr ()) ;
	converter.Triangulate (_scene, true) ; // glTF supports triangles only
	converter.SplitMeshesPerMaterial (_scene, true) ; // Split meshes per material, so we only have one material per mesh (VBO support)
	
	// Set the current peripheral to be the NULL so FBX geometries that have been imported can be flushed
    _scene->SetPeripheral (NULL_PERIPHERAL) ;

	//int nb =_scene->GetSrcObjectCount<FbxNodeAttribute> () ;
	//int nbTot =5 * nb ;
	//int nbRest =4 * nb ;
	//int nbSteps =nbRest / 8 ;

	//FbxArray<FbxNode *> pBadMeshes =RemoveBadPolygonsFromMeshes (_scene) ;

	return (true) ;
}
Example #3
0
osgDB::ReaderWriter::WriteResult ReaderWriterFBX::writeNode(
    const osg::Node& node,
    const std::string& filename,
    const Options* options) const
{
    try
    {
        std::string ext = osgDB::getLowerCaseFileExtension(filename);
        if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;

        osg::ref_ptr<Options> localOptions = options ?
            static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
        localOptions->getDatabasePathList().push_front(osgDB::getFilePath(filename));

        FbxManager* pSdkManager = FbxManager::Create();

        if (!pSdkManager)
        {
            return WriteResult::ERROR_IN_WRITING_FILE;
        }

        CleanUpFbx cleanUpFbx(pSdkManager);

        pSdkManager->SetIOSettings(FbxIOSettings::Create(pSdkManager, IOSROOT));

        bool useFbxRoot = false;
        if (options)
        {
            std::istringstream iss(options->getOptionString());
            std::string opt;
            while (iss >> opt)
            {
                if (opt == "Embedded")
                {
                    pSdkManager->GetIOSettings()->SetBoolProp(EXP_FBX_EMBEDDED, true);
                }
                else if (opt == "UseFbxRoot")
                {
                    useFbxRoot = true;
                }
            }
        }

        FbxScene* pScene = FbxScene::Create(pSdkManager, "");
        pluginfbx::WriterNodeVisitor writerNodeVisitor(pScene, pSdkManager, filename,
            options, osgDB::getFilePath(node.getName().empty() ? filename : node.getName()));
        if (useFbxRoot && isBasicRootNode(node))
        {
            // If root node is a simple group, put all elements under the FBX root
            const osg::Group * osgGroup = node.asGroup();
            for (unsigned int child = 0; child < osgGroup->getNumChildren(); ++child)
            {
                const_cast<osg::Node *>(osgGroup->getChild(child))->accept(writerNodeVisitor);
            }
        }
        else {
            // Normal scene
            const_cast<osg::Node&>(node).accept(writerNodeVisitor);
        }

        FbxDocumentInfo* pDocInfo = pScene->GetDocumentInfo();
        bool needNewDocInfo = pDocInfo != NULL;
        if (needNewDocInfo)
        {
            pDocInfo = FbxDocumentInfo::Create(pSdkManager, "");
        }
        pDocInfo->LastSaved_ApplicationName.Set(FbxString("OpenSceneGraph"));
        pDocInfo->LastSaved_ApplicationVersion.Set(FbxString(osgGetVersion()));
        if (needNewDocInfo)
        {
            pScene->SetDocumentInfo(pDocInfo);
        }

        FbxExporter* lExporter = FbxExporter::Create(pSdkManager, "");
        pScene->GetGlobalSettings().SetAxisSystem(FbxAxisSystem::eOpenGL);

        // Ensure the directory exists or else the FBX SDK will fail
        if (!osgDB::makeDirectoryForFile(filename)) {
            OSG_NOTICE << "Can't create directory for file '" << filename << "'. FBX SDK may fail creating the file." << std::endl;
        }

        // The FBX SDK interprets the filename as UTF-8
#ifdef OSG_USE_UTF8_FILENAME
        const std::string& utf8filename(filename);
#else
        std::string utf8filename(osgDB::convertStringFromCurrentCodePageToUTF8(filename));
#endif

        if (!lExporter->Initialize(utf8filename.c_str()))
        {
#if FBXSDK_VERSION_MAJOR < 2014
            return std::string(lExporter->GetLastErrorString());
#else
            return std::string(lExporter->GetStatus().GetErrorString());
#endif
        }
        if (!lExporter->Export(pScene))
        {
#if FBXSDK_VERSION_MAJOR < 2014
            return std::string(lExporter->GetLastErrorString());
#else
            return std::string(lExporter->GetStatus().GetErrorString());
#endif
        }

        return WriteResult::FILE_SAVED;
    }
    catch (const std::string& s)
    {
        return s;
    }
    catch (const char* s)
    {
        return std::string(s);
    }
    catch (...)
    {
    }

    return WriteResult::ERROR_IN_WRITING_FILE;
}
Example #4
0
// Converts a CC mesh to an FBX mesh
static FbxNode* ToFbxMesh(ccGenericMesh* mesh, FbxScene* pScene, QString filename, size_t meshIndex)
{
	if (!mesh)
		return 0;

	FbxNode* lNode = FbxNode::Create(pScene,qPrintable(mesh->getName()));
	FbxMesh* lMesh = FbxMesh::Create(pScene, qPrintable(mesh->getName()));
	lNode->SetNodeAttribute(lMesh);


	ccGenericPointCloud* cloud = mesh->getAssociatedCloud();
	if (!cloud)
		return 0;
	unsigned vertCount = cloud->size();
	unsigned faceCount = mesh->size();

	// Create control points.
	{
		lMesh->InitControlPoints(vertCount);
		FbxVector4* lControlPoints = lMesh->GetControlPoints();

		for (unsigned i=0; i<vertCount; ++i)
		{
			const CCVector3* P = cloud->getPoint(i);
			lControlPoints[i] = FbxVector4(P->x,P->y,P->z);
			//lControlPoints[i] = FbxVector4(P->x,P->z,-P->y); //DGM: see loadFile (Y and Z are inverted)
		}
	}

	ccMesh* asCCMesh = 0;
	if (mesh->isA(CC_TYPES::MESH))
		asCCMesh = static_cast<ccMesh*>(mesh);

	// normals
	if (mesh->hasNormals())
	{
		FbxGeometryElementNormal* lGeometryElementNormal = lMesh->CreateElementNormal();
		if (mesh->hasTriNormals())
		{
			// We want to have one normal per vertex of each polygon,
			// so we set the mapping mode to eByPolygonVertex.
			lGeometryElementNormal->SetMappingMode(FbxGeometryElement::eByPolygonVertex);
			lGeometryElementNormal->SetReferenceMode(FbxGeometryElement::eIndexToDirect);
			lGeometryElementNormal->GetIndexArray().SetCount(faceCount*3);
			
			if (asCCMesh)
			{
				NormsIndexesTableType* triNorms = asCCMesh->getTriNormsTable();
				assert(triNorms);
				for (unsigned i=0; i<triNorms->currentSize(); ++i)
				{
					const CCVector3& N = ccNormalVectors::GetNormal(triNorms->getValue(i));
					FbxVector4 Nfbx(N.x,N.y,N.z);
					lGeometryElementNormal->GetDirectArray().Add(Nfbx);
				}
				for (unsigned j=0; j<faceCount; ++j)
				{
					int i1,i2,i3;
					asCCMesh->getTriangleNormalIndexes(j,i1,i2,i3);
					lGeometryElementNormal->GetIndexArray().SetAt(static_cast<int>(j)*3+0, i1);
					lGeometryElementNormal->GetIndexArray().SetAt(static_cast<int>(j)*3+1, i2);
					lGeometryElementNormal->GetIndexArray().SetAt(static_cast<int>(j)*3+2, i3);
				}
			}
			else
			{
				for (unsigned j=0; j<faceCount; ++j)
				{
					//we can't use the 'NormsIndexesTable' so we save all the normals of all the vertices
					CCVector3 Na,Nb,Nc;
					lGeometryElementNormal->GetDirectArray().Add(FbxVector4(Na.x,Na.y,Na.z));
					lGeometryElementNormal->GetDirectArray().Add(FbxVector4(Nb.x,Nb.y,Nb.z));
					lGeometryElementNormal->GetDirectArray().Add(FbxVector4(Nc.x,Nc.y,Nc.z));
					
					mesh->getTriangleNormals(j,Na,Nb,Nc);
					lGeometryElementNormal->GetIndexArray().SetAt(static_cast<int>(j)*3+0, static_cast<int>(j)*3+0);
					lGeometryElementNormal->GetIndexArray().SetAt(static_cast<int>(j)*3+1, static_cast<int>(j)*3+1);
					lGeometryElementNormal->GetIndexArray().SetAt(static_cast<int>(j)*3+2, static_cast<int>(j)*3+2);
				}
			}
		}
		else
		{
			// We want to have one normal for each vertex (or control point),
			// so we set the mapping mode to eByControlPoint.
			lGeometryElementNormal->SetMappingMode(FbxGeometryElement::eByControlPoint);
			// The first method is to set the actual normal value
			// for every control point.
			lGeometryElementNormal->SetReferenceMode(FbxGeometryElement::eDirect);
			for (unsigned i=0; i<vertCount; ++i)
			{
				const CCVector3& N = cloud->getPointNormal(i);
				FbxVector4 Nfbx(N.x,N.y,N.z);
				lGeometryElementNormal->GetDirectArray().Add(Nfbx);
			}
		}
	}
	else
	{
		ccLog::Warning("[FBX] Mesh has no normal! You can manually compute them (select it then call \"Edit > Normals > Compute\")");
	}

	// Set material mapping.
	bool hasMaterial = false;
	if (asCCMesh && asCCMesh->hasMaterials())
	{
		const ccMaterialSet* matSet = asCCMesh->getMaterialSet();
		size_t matCount = matSet->size();

		//check if we have textures
		bool hasTextures = asCCMesh->hasTextures();
		if (hasTextures)
		{
			//check that we actually have materials with textures as well!
			hasTextures = false;
			for (size_t i=0; i<matCount; ++i)
			{
				ccMaterial::CShared mat = matSet->at(i);
				if (mat->hasTexture())
				{
					hasTextures = true;
					break;
				}
			}
		}

		static const char gDiffuseElementName[] = "DiffuseUV";

		// Create UV for Diffuse channel
		if (hasTextures)
		{
			FbxGeometryElementUV* lUVDiffuseElement = lMesh->CreateElementUV(gDiffuseElementName);
			assert(lUVDiffuseElement != 0);
			lUVDiffuseElement->SetMappingMode(FbxGeometryElement::eByPolygonVertex);
			lUVDiffuseElement->SetReferenceMode(FbxGeometryElement::eIndexToDirect);

			//fill Direct Array
			const TextureCoordsContainer* texCoords = asCCMesh->getTexCoordinatesTable();
			assert(texCoords);
			if (texCoords)
			{
				unsigned count = texCoords->currentSize();
				lUVDiffuseElement->GetDirectArray().SetCount(static_cast<int>(count));
				for (unsigned i=0; i<count; ++i)
				{
					const float* uv = texCoords->getValue(i);
					lUVDiffuseElement->GetDirectArray().SetAt(i,FbxVector2(uv[0],uv[1]));
				}
			}

			//fill Indexes Array
			assert(asCCMesh->hasPerTriangleTexCoordIndexes());
			if (asCCMesh->hasPerTriangleTexCoordIndexes())
			{
				unsigned triCount = asCCMesh->size();
				lUVDiffuseElement->GetIndexArray().SetCount(static_cast<int>(3*triCount));
				for (unsigned j=0; j<triCount; ++j)
				{
					int t1=0, t2=0, t3=0;
					asCCMesh->getTriangleTexCoordinatesIndexes(j, t1, t2, t3);

					lUVDiffuseElement->GetIndexArray().SetAt(j*3+0,t1);
					lUVDiffuseElement->GetIndexArray().SetAt(j*3+1,t2);
					lUVDiffuseElement->GetIndexArray().SetAt(j*3+2,t3);
				}
			}
		}

		//Textures used in this file
		QMap<QString,QString> texFilenames;
		//directory to save textures (if any)
		QFileInfo info(filename);
		QString textDirName = info.baseName() + QString(".fbm");
		QDir baseDir = info.absoluteDir();
		QDir texDir = QDir(baseDir.absolutePath() + QString("/") + textDirName);

		for (size_t i=0; i<matCount; ++i)
		{
			ccMaterial::CShared mat = matSet->at(i);
			FbxSurfacePhong *lMaterial = FbxSurfacePhong::Create(pScene, qPrintable(mat->getName()));

			const ccColor::Rgbaf& emission = mat->getEmission();
			const ccColor::Rgbaf& ambient = mat->getAmbient();
			const ccColor::Rgbaf& diffuse = mat->getDiffuseFront();
			const ccColor::Rgbaf& specular = mat->getDiffuseFront();
			lMaterial->Emissive.Set(FbxDouble3(emission.r,emission.g,emission.b));
			lMaterial->Ambient .Set(FbxDouble3( ambient.r, ambient.g, ambient.b));
			lMaterial->Diffuse .Set(FbxDouble3( diffuse.r, diffuse.g, diffuse.b));
			lMaterial->Specular.Set(FbxDouble3(specular.r,specular.g,specular.b));
			lMaterial->Shininess = mat->getShininessFront();
			lMaterial->ShadingModel.Set("Phong");

			if (hasTextures && mat->hasTexture())
			{
				QString texFilename = mat->getTextureFilename();
				
				//texture has not already been processed
				if (!texFilenames.contains(texFilename))
				{
					//if necessary, we (try to) create a subfolder to store textures
					if (!texDir.exists())
					{
						texDir = baseDir;
						if (texDir.mkdir(textDirName))
						{
							texDir.cd(textDirName);
						}
						else
						{
							textDirName = QString();
							ccLog::Warning("[FBX] Failed to create subfolder '%1' to store texture files (files will be stored next to the .fbx file)");
						}
					}

					QFileInfo fileInfo(texFilename);
					QString baseTexName = fileInfo.fileName();
					//add extension
					QString extension = QFileInfo(texFilename).suffix();
					if (fileInfo.suffix().isEmpty())
						baseTexName += QString(".png");

					QString absoluteFilename = texDir.absolutePath() + QString("/") + baseTexName;
					ccLog::PrintDebug(QString("[FBX] Material '%1' texture: %2").arg(mat->getName()).arg(absoluteFilename));

					texFilenames[texFilename] = absoluteFilename;
				}
				//mat.texture.save(absoluteFilename);

				// Set texture properties.
				FbxFileTexture* lTexture = FbxFileTexture::Create(pScene,"DiffuseTexture");
				assert(!texFilenames[texFilename].isEmpty());
				lTexture->SetFileName(qPrintable(texFilenames[texFilename]));
				lTexture->SetTextureUse(FbxTexture::eStandard);
				lTexture->SetMappingType(FbxTexture::eUV);
				lTexture->SetMaterialUse(FbxFileTexture::eModelMaterial);
				lTexture->SetSwapUV(false);
				lTexture->SetTranslation(0.0, 0.0);
				lTexture->SetScale(1.0, 1.0);
				lTexture->SetRotation(0.0, 0.0);
				lTexture->UVSet.Set(FbxString(gDiffuseElementName)); // Connect texture to the proper UV

				// don't forget to connect the texture to the corresponding property of the material
				lMaterial->Diffuse.ConnectSrcObject(lTexture);
			}

			int matIndex = lNode->AddMaterial(lMaterial);
			assert(matIndex  == static_cast<int>(i));
		}

		//don't forget to save the texture files
		{
			for (QMap<QString,QString>::ConstIterator it = texFilenames.begin(); it != texFilenames.end(); ++it)
			{
				const QImage image = ccMaterial::GetTexture(it.key());
				image.mirrored().save(it.value());
			}
			
			texFilenames.clear(); //don't need this anymore!
		}

		// Create 'triangle to material index' mapping
		{
			FbxGeometryElementMaterial* lMaterialElement = lMesh->CreateElementMaterial();
			lMaterialElement->SetMappingMode(FbxGeometryElement::eByPolygon);
			lMaterialElement->SetReferenceMode(FbxGeometryElement::eIndexToDirect);
		}

		hasMaterial = true;
	}

	// colors
	if (cloud->hasColors())
	{
		FbxGeometryElementVertexColor* lGeometryElementVertexColor = lMesh->CreateElementVertexColor();
		lGeometryElementVertexColor->SetMappingMode(FbxGeometryElement::eByControlPoint);
		lGeometryElementVertexColor->SetReferenceMode(FbxGeometryElement::eDirect);
		lGeometryElementVertexColor->GetDirectArray().SetCount(vertCount);
		for (unsigned i=0; i<vertCount; ++i)
		{
			const colorType* C = cloud->getPointColor(i);
			FbxColor col(	static_cast<double>(C[0])/ccColor::MAX,
							static_cast<double>(C[1])/ccColor::MAX,
							static_cast<double>(C[2])/ccColor::MAX );
			lGeometryElementVertexColor->GetDirectArray().SetAt(i,col);
		}

		if (!hasMaterial)
		{
			//it seems that we have to create a fake material in order for the colors to be displayed (in Unity and FBX Review at least)!
			FbxSurfacePhong *lMaterial = FbxSurfacePhong::Create(pScene, "ColorMaterial");

			lMaterial->Emissive.Set(FbxDouble3(0,0,0));
			lMaterial->Ambient.Set(FbxDouble3(0,0,0));
			lMaterial->Diffuse.Set(FbxDouble3(1,1,1));
			lMaterial->Specular.Set(FbxDouble3(0,0,0));
			lMaterial->Shininess = 0;
			lMaterial->ShadingModel.Set("Phong");

			FbxGeometryElementMaterial* lMaterialElement = lMesh->CreateElementMaterial();
			lMaterialElement->SetMappingMode(FbxGeometryElement::eAllSame);
			lMaterialElement->SetReferenceMode(FbxGeometryElement::eDirect);
			lNode->AddMaterial(lMaterial);
		}
	}

	// Create polygons
	{
		for (unsigned j=0; j<faceCount; ++j)
		{
			const CCLib::TriangleSummitsIndexes* tsi = mesh->getTriangleIndexes(j);

			int matIndex = hasMaterial ? asCCMesh->getTriangleMtlIndex(j) : -1;
			lMesh->BeginPolygon(matIndex);
			lMesh->AddPolygon(tsi->i1);
			lMesh->AddPolygon(tsi->i2);
			lMesh->AddPolygon(tsi->i3);
			lMesh->EndPolygon();
		}
	}

	return lNode;
}
Example #5
0
bool SceneConverter::convert()
{
    //
    // Construt the scene
    //
    FbxNode *node = m_scene->GetRootNode();
    std::list<FbxNode *> nodes;
    std::map<FbxNode *, SceneNode *> fbxNode2SceneNodes;
    Scene scene;

    nodes.push_back(node);
    SceneNode *sceneNode = makeSceneNode(node);
    scene.addNode(sceneNode);
    fbxNode2SceneNodes.insert(std::make_pair(node, sceneNode));

    while (!nodes.empty())
    {
        FbxNode *ret = nodes.front();
        nodes.pop_front();

        for (int i = 0; i < ret->GetChildCount(); i++)
        {
            FbxNode *child = ret->GetChild(i);
            
            // Only output visible nodes.
            if (child->GetVisibility() && child->Show.Get())
            {
                SceneNode *sceneNode = makeSceneNode(child);
                if (sceneNode != NULL)
                {
                    if (sceneNode->type == "camera")
                    {
                        // The first camera will be the main camera of the scene
                        scene.setCamera(sceneNode);
                    }
                    scene.addNode(sceneNode, fbxNode2SceneNodes[ret]);
                    fbxNode2SceneNodes.insert(std::make_pair(child, sceneNode));
                }
            
                nodes.push_back(child);
            }
        }
    }

    // Create a camera if it is not included in FBX. The camera is evaluated
    // using the bounding box of all visible nodes.
    if (m_numCameras == 0)
    {
        FbxVector4 rootBboxMin;
        FbxVector4 rootBboxMax;
        FbxVector4 rootBboxCenter;

        rootBboxMin = FbxVector4(FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX);
        rootBboxMax = FbxVector4(-FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX);
    
        FbxNode *node = m_scene->GetRootNode();

        nodes.push_back(node);

        while (!nodes.empty())
        {
            FbxNode *ret = nodes.front();
            nodes.pop_front();

            for (int i = 0; i < ret->GetChildCount(); i++)
            {
                FbxNode *child = ret->GetChild(i);
                
                nodes.push_back(child);
            }
                
            if (ret->GetChildCount() == 0 &&
                ret->GetVisibility() && 
                ret->Show.Get() &&
                ret->GetMesh() != NULL)
            {
                FbxVector4 bboxMin;
                FbxVector4 bboxMax;
                FbxVector4 bboxCenter;

                ret->EvaluateGlobalBoundingBoxMinMaxCenter(bboxMin, bboxMax, bboxCenter);

                rootBboxMin[0] = std::min(rootBboxMin[0], bboxMin[0]);
                rootBboxMin[1] = std::min(rootBboxMin[1], bboxMin[1]);
                rootBboxMin[2] = std::min(rootBboxMin[2], bboxMin[2]);
                
                rootBboxMax[0] = std::max(rootBboxMax[0], bboxMax[0]);
                rootBboxMax[1] = std::max(rootBboxMax[1], bboxMax[1]);
                rootBboxMax[2] = std::max(rootBboxMax[2], bboxMax[2]);
            }
        }

        rootBboxCenter = (rootBboxMin + rootBboxMax) / 2;
        FbxVector4 rootBboxSize = rootBboxMax - rootBboxMin;
            
        SceneNode *sceneNode = new SceneNode();

        sceneNode->type = FbxString("camera");
        sceneNode->attributes.push_back(std::make_pair(FbxString("name"), FbxString("camera")));
        sceneNode->attributes.push_back(std::make_pair(FbxString("fixed"), FbxString("true")));

        double diag = sqrt(rootBboxSize[0] * rootBboxSize[0] + 
                           rootBboxSize[1] * rootBboxSize[1] + 
                           rootBboxSize[2] * rootBboxSize[2]) * 0.5;
            
        double eye = diag / tan(15.0 * FBXSDK_PI_DIV_180);

        double position[3];
        double up[3];
        double znear;
        double zfar;
            
        znear = eye - diag - 1.0f;
        zfar  = eye + diag + 1.0f;

        if (rootBboxSize[0] <= rootBboxSize[1] && rootBboxSize[0] <= rootBboxSize[2])
        {
            position[0] = eye + rootBboxCenter[0]; 
            position[1] = rootBboxCenter[1];
            position[2] = rootBboxCenter[2];

            up[0] = 0;
            up[1] = 1;
            up[2] = 0;
        }
        else if (rootBboxSize[1] <= rootBboxSize[0] && rootBboxSize[1] <= rootBboxSize[2])
        {
            position[0] = rootBboxCenter[0]; 
            position[1] = eye + rootBboxCenter[1];
            position[2] = rootBboxCenter[2];

            up[0] = 0;
            up[1] = 0;
            up[2] = 1;
        }
        else
        {
            position[0] = rootBboxCenter[0]; 
            position[1] = rootBboxCenter[1];
            position[2] = eye + rootBboxCenter[2];

            up[0] = 0;
            up[1] = 1;
            up[2] = 0;
        }

        char lookat[1024];
        char perspective[1024];
            
        FBXSDK_sprintf(lookat, 1024, "eye:%8.5f,%8.5f,%8.5f,center:%8.5f,%8.5f,%8.5f,up:%8.5f,%8.5f,%8.5f",
                    (float)position[0], (float)position[1], (float)position[2],
                    (float)rootBboxCenter[0], (float)rootBboxCenter[1], (float)rootBboxCenter[2],
                    (float)up[0], (float)up[1], (float)up[2]);
        sceneNode->attributes.push_back(std::make_pair(FbxString("lookat"), FbxString(lookat)));
            
        FBXSDK_sprintf(perspective, 1024, "perspective,fov:%8.5f,aspect:-1,znear:%8.5f,zfar:%8.5f",
                    30.0f, (float)znear, (float)zfar);
        sceneNode->attributes.push_back(std::make_pair(FbxString("projection"), FbxString(perspective)));
                    
        scene.setCamera(sceneNode);
        scene.addNode(sceneNode, scene.root());
    }

    //
    // Output the file.
    //
    //FbxString outputFilename = FbxPathUtils::GetFileName(m_arguments->FBXFileName.Buffer()).Lower();
    //outputFilename.FindAndReplace(".fbx", ".psc");
    FbxString outputFilename("scene.psc");
    FbxString path = FbxPathUtils::Bind(m_arguments->outputFolder, outputFilename.Buffer());
    bool ret = scene.output(path.Buffer());

    if (!ret)
    {
        FBXSDK_printf("Exporting failed!\n\n");
    }

    return ret;
}
Example #6
0
SceneNode *SceneConverter::makeSceneNode(FbxNode *node)
{
    SceneNode *sceneNode = new SceneNode();

    if (node->GetParent() == NULL) // The root
    {
        // Type
        sceneNode->type = FbxString("root");
        
        // Name
        sceneNode->attributes.push_back(std::make_pair(FbxString("name"), node->GetName()));
        
        // Transformation
        FbxAMatrix m = node->EvaluateGlobalTransform();

        const FbxVector4 translation = m.GetT();
        const FbxVector4 rotation    = m.GetR();
        const FbxVector4 scaling     = m.GetS();
        
        char buffer[1024];
        FBXSDK_sprintf(buffer, 1024, "s:%8.5f,%8.5f,%8.5f,r:%8.5f,%8.5f,%8.5f,t:%8.5f,%8.5f,%8.5f",
            (float)scaling[0], (float)scaling[1], (float)scaling[2],
            (float)rotation[0], (float)rotation[1], (float)rotation[2],
            (float)translation[0], (float)translation[1], (float)translation[2]);

        sceneNode->attributes.push_back(std::make_pair(FbxString("transform"), FbxString(buffer)));
    }
    else
    {
        FbxCamera *camera = node->GetCamera();
        if (camera != NULL)
        {
            sceneNode->type = FbxString("camera");
        
            sceneNode->attributes.push_back(std::make_pair(FbxString("name"), node->GetName()));

            sceneNode->attributes.push_back(std::make_pair(FbxString("fixed"), FbxString("true")));

            FbxVector4 position = camera->EvaluatePosition();
            FbxVector4 center = camera->EvaluateLookAtPosition();
            // FIXME: seems EvaluateUpDirection doesn't give correct result as it 
            // is affected by its parent nodes' tranforms however we attach camera
            // to the root in paper3d's scene.
            // FbxVector4 up = camera->EvaluateUpDirection(position, center);
            FbxDouble3 up = camera->UpVector.Get();

            char buffer[1024];
            FBXSDK_sprintf(buffer, 1024, "eye:%8.5f,%8.5f,%8.5f,center:%8.5f,%8.5f,%8.5f,up:%8.5f,%8.5f,%8.5f",
                    (float)position[0], (float)position[1], (float)position[2],
                    (float)center[0], (float)center[1], (float)center[2],
                    (float)up[0], (float)up[1], (float)up[2]);
            sceneNode->attributes.push_back(std::make_pair(FbxString("lookat"), FbxString(buffer)));

            float nearZ = (float)camera->GetNearPlane();
            float farZ = (float)camera->GetFarPlane();

            if (camera->ProjectionType.Get() == FbxCamera::ePerspective)
            {
                FbxCamera::EAspectRatioMode lCamAspectRatioMode = camera->GetAspectRatioMode();
                double lAspectX = camera->AspectWidth.Get();
                double lAspectY = camera->AspectHeight.Get();
                double lAspectRatio = 1.333333;
                switch( lCamAspectRatioMode)
                {
                    case FbxCamera::eWindowSize:
                        lAspectRatio = lAspectX / lAspectY;
                        break;
                    case FbxCamera::eFixedRatio:
                        lAspectRatio = lAspectX;

                        break;
                    case FbxCamera::eFixedResolution:
                        lAspectRatio = lAspectX / lAspectY * camera->GetPixelRatio();
                        break;
                    case FbxCamera::eFixedWidth:
                        lAspectRatio = camera->GetPixelRatio() / lAspectY;
                        break;
                    case FbxCamera::eFixedHeight:
                        lAspectRatio = camera->GetPixelRatio() * lAspectX;
                        break;
                    default:
                        break;

                }

                //get the aperture ratio
                double lFilmHeight = camera->GetApertureHeight();
                double lFilmWidth = camera->GetApertureWidth() * camera->GetSqueezeRatio();
                //here we use Height : Width
                double lApertureRatio = lFilmHeight / lFilmWidth;

                //change the aspect ratio to Height : Width
                lAspectRatio = 1 / lAspectRatio;
                //revise the aspect ratio and aperture ratio
                FbxCamera::EGateFit lCameraGateFit = camera->GateFit.Get();
                switch( lCameraGateFit )
                {

                    case FbxCamera::eFitFill:
                        if( lApertureRatio > lAspectRatio)  // the same as eHORIZONTAL_FIT
                        {
                            lFilmHeight = lFilmWidth * lAspectRatio;
                            camera->SetApertureHeight( lFilmHeight);
                            lApertureRatio = lFilmHeight / lFilmWidth;
                        }
                        else if( lApertureRatio < lAspectRatio) //the same as eVERTICAL_FIT
                        {
                            lFilmWidth = lFilmHeight / lAspectRatio;
                            camera->SetApertureWidth( lFilmWidth);
                            lApertureRatio = lFilmHeight / lFilmWidth;
                        }
                        break;
                    case FbxCamera::eFitVertical:
                        lFilmWidth = lFilmHeight / lAspectRatio;
                        camera->SetApertureWidth( lFilmWidth);
                        lApertureRatio = lFilmHeight / lFilmWidth;
                        break;
                    case FbxCamera::eFitHorizontal:
                        lFilmHeight = lFilmWidth * lAspectRatio;
                        camera->SetApertureHeight( lFilmHeight);
                        lApertureRatio = lFilmHeight / lFilmWidth;
                        break;
                    case FbxCamera::eFitStretch:
                        lAspectRatio = lApertureRatio;
                        break;
                    case FbxCamera::eFitOverscan:
                        if( lFilmWidth > lFilmHeight)
                        {
                            lFilmHeight = lFilmWidth * lAspectRatio;
                        }
                        else
                        {
                            lFilmWidth = lFilmHeight / lAspectRatio;
                        }
                        lApertureRatio = lFilmHeight / lFilmWidth;
                        break;
                    case FbxCamera::eFitNone:
                    default:
                        break;
                }
                //change the aspect ratio to Width : Height
                lAspectRatio = 1 / lAspectRatio;

#define HFOV2VFOV(h, ar) (2.0 * atan((ar) * tan( (h * FBXSDK_PI_DIV_180) * 0.5)) * FBXSDK_180_DIV_PI) //ar : aspectY / aspectX
#define VFOV2HFOV(v, ar) (2.0 * atan((ar) * tan( (v * FBXSDK_PI_DIV_180) * 0.5)) * FBXSDK_180_DIV_PI) //ar : aspectX / aspectY
                double lFieldOfViewX = 0.0;
                double lFieldOfViewY = 0.0;
                if (camera->GetApertureMode() == FbxCamera::eVertical)
                {
                    lFieldOfViewY = camera->FieldOfView.Get();
                    lFieldOfViewX = VFOV2HFOV( lFieldOfViewY, 1 / lApertureRatio);
                }
                else if (camera->GetApertureMode() == FbxCamera::eHorizontal)
                {
                    lFieldOfViewX = camera->FieldOfView.Get(); //get HFOV
                    lFieldOfViewY = HFOV2VFOV( lFieldOfViewX, lApertureRatio);
                }
                else if (camera->GetApertureMode() == FbxCamera::eFocalLength)
                {
                    lFieldOfViewX = camera->ComputeFieldOfView(camera->FocalLength.Get());    //get HFOV
                    lFieldOfViewY = HFOV2VFOV( lFieldOfViewX, lApertureRatio);
                }
                else if (camera->GetApertureMode() == FbxCamera::eHorizAndVert) 
                {
                    lFieldOfViewX = camera->FieldOfViewX.Get();
                    lFieldOfViewY = camera->FieldOfViewY.Get();
                }
#undef HFOV2VFOV
#undef VFOV2HFOV

                FBXSDK_sprintf(buffer, 1024, "perspective,fov:%8.5f,aspect:-1,znear:%8.5f,zfar:%8.5f",
                        (float)lFieldOfViewY, nearZ, farZ);
                sceneNode->attributes.push_back(std::make_pair(FbxString("projection"), FbxString(buffer)));

            }
            else
            {
                FBXSDK_sprintf(buffer, 1024, "orthogonal,aspect:-1,znear:%8.5f,zfar:%8.5f", nearZ, farZ);
                sceneNode->attributes.push_back(std::make_pair(FbxString("projection"), FbxString(buffer)));
            }

                
            m_numCameras++;
        }
        else
        {
            FbxLight *light = node->GetLight();
            if (light != NULL)
            {
                m_numLights++;

                FBX_ASSERT(!"Not implemented!");
            }
            else
            {
                // Type
                sceneNode->type = FbxString("drawable");

                // Name
                sceneNode->attributes.push_back(std::make_pair(FbxString("name"), node->GetName()));

                // Transformation
                FbxAMatrix m = node->EvaluateLocalTransform();
                //FbxAMatrix m1 = node->EvaluateGlobalTransform();


                const FbxVector4 translation = m.GetT();
                const FbxVector4 rotation    = m.GetR();
                const FbxVector4 scaling     = m.GetS();

                float s[3], r[3], t[3];
                t[0] = (float)translation.mData[0];
                t[1] = (float)translation.mData[1];
                t[2] = (float)translation.mData[2];

                r[0] = (float)(rotation[0] * FBXSDK_DEG_TO_RAD);
                r[1] = (float)(rotation[1] * FBXSDK_DEG_TO_RAD);
                r[2] = (float)(rotation[2] * FBXSDK_DEG_TO_RAD);

                s[0] = (float)scaling[0];
                s[1] = (float)scaling[1];
                s[2] = (float)scaling[2];

                //const FbxVector4 translation1 = m1.GetT();
                //const FbxVector4 rotation1    = m1.GetR();
                //const FbxVector4 scaling1     = m1.GetS();


                char buffer[1024];
                FBXSDK_sprintf(buffer, 1024, "s:%8.5f,%8.5f,%8.5f,r:%8.5f,%8.5f,%8.5f,t:%8.5f,%8.5f,%8.5f",
                        s[0], s[1], s[2], r[0], r[1], r[2], t[0], t[1], t[2]);

                sceneNode->attributes.push_back(std::make_pair(FbxString("transform"), FbxString(buffer)));

                // Mesh
                //if (node->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::eCamera)
                //{
                //    FBXSDK_printf("f**k");
                //}

                static FbxUInt32 i = 0;
                if (node->GetMesh() == NULL)
                {
                    sceneNode->type = FbxString("node");
                }
                else
                {
                    const char *meshName = node->GetMesh()->GetName();
                    if (meshName == NULL || meshName[0] == 0)
                    {
                        meshName = node->GetName();
                    }

                    FbxString prefix;
                    if (meshName == NULL || meshName[0] == 0)
                    {
                        prefix = FbxString("mesh_") + FbxString(int(i++));
                    }
                    else
                    {
                        prefix = FbxString(meshName);
                    }
                    sceneNode->geometry = prefix + FbxString(".") + m_arguments->meshFormat;

                    // Material
                    FbxSurfaceMaterial *material = node->GetMaterial(0); 

                    if (material != NULL)
                    {
                        // This only gets the material of type sDiffuse, you probably need to
                        // traverse all Standard Material Property by its name to get all
                        // possible textures.
                        FbxProperty prop = material->FindProperty(FbxSurfaceMaterial::sDiffuse);

                        // Check if it's layeredtextures
                        int layeredTextureCount = prop.GetSrcObjectCount<FbxLayeredTexture>();

                        if (prop.GetSrcObjectCount<FbxTexture>() > 0)
                        {
                            FbxFileTexture *lTex = prop.GetSrcObject<FbxFileTexture>(0);
                            FbxString filename = FbxPathUtils::GetFileName(lTex->GetFileName());
                            sceneNode->texture = filename.Lower();

                            m_textures.push_back(FbxString(lTex->GetFileName()));
                        }

                        // root node is not counted as a drawable.
                        m_numDrawables++;
                    }
                }
            }
        }
    }
    
    return sceneNode;
}
osgDB::ReaderWriter::WriteResult ReaderWriterFBX::writeNode(
    const osg::Node& node,
    const std::string& filename,
    const Options* options) const
{
    try
    {
        std::string ext = osgDB::getLowerCaseFileExtension(filename);
        if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;

        osg::ref_ptr<Options> localOptions = options ?
            static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options;
        localOptions->getDatabasePathList().push_front(osgDB::getFilePath(filename));

        FbxManager* pSdkManager = FbxManager::Create();

        if (!pSdkManager)
        {
            return WriteResult::ERROR_IN_WRITING_FILE;
        }

        CleanUpFbx cleanUpFbx(pSdkManager);

        pSdkManager->SetIOSettings(FbxIOSettings::Create(pSdkManager, IOSROOT));

        bool useFbxRoot = false;
        bool ascii(false);
        std::string exportVersion;
        if (options)
        {
            std::istringstream iss(options->getOptionString());
            std::string opt;
            while (iss >> opt)
            {
                if (opt == "Embedded")
                {
                    pSdkManager->GetIOSettings()->SetBoolProp(EXP_FBX_EMBEDDED, true);
                }
                else if (opt == "UseFbxRoot")
                {
                    useFbxRoot = true;
                }
                else if (opt == "FBX-ASCII")
                {
                    ascii = true;
                }
                else if (opt == "FBX-ExportVersion")
                {
                    iss >> exportVersion;
                }
            }
        }

        FbxScene* pScene = FbxScene::Create(pSdkManager, "");

        if (options)
        {
            if (options->getPluginData("FBX-AssetUnitMeter"))
            {
                float unit = *static_cast<const float*>(options->getPluginData("FBX-AssetUnitMeter"));
                FbxSystemUnit kFbxSystemUnit(unit*100);
                pScene->GetGlobalSettings().SetSystemUnit(kFbxSystemUnit);
            }
        }

        pluginfbx::WriterNodeVisitor writerNodeVisitor(pScene, pSdkManager, filename,
            options, osgDB::getFilePath(node.getName().empty() ? filename : node.getName()));
        if (useFbxRoot && isBasicRootNode(node))
        {
            // If root node is a simple group, put all elements under the FBX root
            const osg::Group * osgGroup = node.asGroup();
            for (unsigned int child = 0; child < osgGroup->getNumChildren(); ++child)
            {
                const_cast<osg::Node *>(osgGroup->getChild(child))->accept(writerNodeVisitor);
            }
        }
        else {
            // Normal scene
            const_cast<osg::Node&>(node).accept(writerNodeVisitor);
        }

        FbxDocumentInfo* pDocInfo = pScene->GetDocumentInfo();
        bool needNewDocInfo = pDocInfo != NULL;
        if (needNewDocInfo)
        {
            pDocInfo = FbxDocumentInfo::Create(pSdkManager, "");
        }
        pDocInfo->LastSaved_ApplicationName.Set(FbxString("OpenSceneGraph"));
        pDocInfo->LastSaved_ApplicationVersion.Set(FbxString(osgGetVersion()));
        if (needNewDocInfo)
        {
            pScene->SetDocumentInfo(pDocInfo);
        }

        FbxExporter* lExporter = FbxExporter::Create(pSdkManager, "");
        pScene->GetGlobalSettings().SetAxisSystem(FbxAxisSystem::eOpenGL);

        // Ensure the directory exists or else the FBX SDK will fail
        if (!osgDB::makeDirectoryForFile(filename)) {
            OSG_NOTICE << "Can't create directory for file '" << filename << "'. FBX SDK may fail creating the file." << std::endl;
        }

        // The FBX SDK interprets the filename as UTF-8
#ifdef OSG_USE_UTF8_FILENAME
        const std::string& utf8filename(filename);
#else
        std::string utf8filename(osgDB::convertStringFromCurrentCodePageToUTF8(filename));
#endif

        // Output format selection. Here we only handle "recent" FBX, binary or ASCII.
        // pSdkManager->GetIOPluginRegistry()->GetWriterFormatDescription() / GetReaderFormatCount() gives the following list:
        //FBX binary (*.fbx)
        //FBX ascii (*.fbx)
        //FBX encrypted (*.fbx)
        //FBX 6.0 binary (*.fbx)
        //FBX 6.0 ascii (*.fbx)
        //FBX 6.0 encrypted (*.fbx)
        //AutoCAD DXF (*.dxf)
        //Alias OBJ (*.obj)
        //Collada DAE (*.dae)
        //Biovision BVH (*.bvh)
        //Motion Analysis HTR (*.htr)
        //Motion Analysis TRC (*.trc)
        //Acclaim ASF (*.asf)
        int format = ascii ? pSdkManager->GetIOPluginRegistry()->FindWriterIDByDescription("FBX ascii (*.fbx)") : -1;        // -1 = Default
        if (!lExporter->Initialize(utf8filename.c_str(), format))
        {
#if FBXSDK_VERSION_MAJOR < 2014
            return std::string(lExporter->GetLastErrorString());
#else
            return std::string(lExporter->GetStatus().GetErrorString());
#endif
        }

        if (!exportVersion.empty() && !lExporter->SetFileExportVersion(FbxString(exportVersion.c_str()), FbxSceneRenamer::eNone)) {
            std::stringstream versionsStr;
            char const * const * versions = lExporter->GetCurrentWritableVersions();
            if (versions) for(; *versions; ++versions) versionsStr << " " << *versions;
            OSG_WARN << "Can't set FBX export version to '" << exportVersion << "'. Using default. Available export versions are:" << versionsStr.str() << std::endl;
        }

        if (!lExporter->Export(pScene))
        {
#if FBXSDK_VERSION_MAJOR < 2014
            return std::string(lExporter->GetLastErrorString());
#else
            return std::string(lExporter->GetStatus().GetErrorString());
#endif
        }

        return WriteResult::FILE_SAVED;
    }
Example #8
0
FbxString ofxFBXNode::getFbxName() {
    return FbxString( name.c_str() );
}