-
-
Save JokerMartini/645f27f94a011936225e910eb326960e to your computer and use it in GitHub Desktop.
FBX Python SDK sample cube and cylinder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import fbx | |
import sys | |
import math | |
############################################################### | |
# Helper Function(s). # | |
############################################################### | |
def makeMaterial( pScene, materialName, **kwargs ): | |
global fbxManager | |
lMaterialName = materialName | |
lShadingName = "Phong" | |
lBlack = fbx.FbxDouble3(0.0, 0.0, 0.0) | |
lRed = fbx.FbxDouble3(1.0, 0.0, 0.0) | |
if kwargs.has_key("diffuse"): | |
diffuse = kwargs["diffuse"] | |
diffuse = fbx.FbxDouble3(diffuse[0], diffuse[1], diffuse[2]) | |
else: | |
diffuse = lRed | |
if kwargs.has_key("ambient"): | |
ambient = kwargs["ambient"] | |
ambient = fbx.FbxDouble3(ambient[0], ambient[1], ambient[2]) | |
else: | |
ambient = lRed | |
if kwargs.has_key("specular"): | |
specular = kwargs["specular"] | |
specular = fbx.FbxDouble3(specular[0], specular[1], specular[2]) | |
else: | |
specular = lBlack | |
if kwargs.has_key("emissive"): | |
emissive = kwargs["emissive"] | |
emissive = fbx.FbxDouble3(emissive[0], emissive[1], emissive[2]) | |
else: | |
emissive = lBlack | |
if kwargs.has_key("transparency"): | |
transpaency = kwargs["transparency"] | |
else: | |
transparency = 0.5 | |
if kwargs.has_key("shininess"): | |
shininess = kwargs["shininess"] | |
else: | |
shininess = 0.5 | |
if kwargs.has_key("specularity"): | |
specularity = kwargs["specularity"] | |
else: | |
specularity = 0.3 | |
lMaterial = fbx.FbxSurfacePhong.Create(fbxManager, lMaterialName) | |
# Generate primary and secondary colors. | |
lMaterial.Emissive.Set(emissive) | |
lMaterial.Ambient.Set(ambient) | |
lMaterial.AmbientFactor.Set(1.) | |
# Add texture for diffuse channel | |
lMaterial.Diffuse.Set(diffuse) | |
lMaterial.DiffuseFactor.Set(1.) | |
lMaterial.TransparencyFactor.Set(transparency) | |
lMaterial.ShadingModel.Set(lShadingName) | |
lMaterial.Shininess.Set(shininess) | |
lMaterial.Specular.Set(specular) | |
lMaterial.SpecularFactor.Set(specularity) | |
return lMaterial | |
# | |
# Cylinder | |
# | |
def makeCylinder( pScene, cylinderName, cylinderHeight, cylinderRadius ): | |
cylinderTop = fbx.FbxVector4(0.0,cylinderHeight * 0.5, 0.0) | |
cylinderBottom = fbx.FbxVector4(0.0,cylinderHeight * -0.5, 0.0) | |
A = fbx.FbxVector4(cylinderRadius, 0.0, 0.0) | |
B = fbx.FbxVector4(0.0, 0.0, cylinderRadius) | |
vertices = [] | |
step = 5 | |
for i in range(0,360,step): | |
theta = float(i) * (1.0/180.0) * math.pi | |
q0 = cylinderTop + A * math.cos(theta) + B * math.sin(theta) | |
q1 = cylinderBottom + A * math.cos(theta) + B * math.sin(theta) | |
theta = float(i + step) * (1.0/180.0) * math.pi | |
q2 = cylinderBottom + A * math.cos(theta) + B * math.sin(theta) | |
q3 = cylinderTop + A * math.cos(theta) + B * math.sin(theta) | |
# first side facet | |
vertices.append(q0) | |
vertices.append(q1) | |
vertices.append(q2) | |
vertices.append(q3) | |
facets = (len(vertices) / 4) | |
cylinderMesh = fbx.FbxMesh.Create( pScene, cylinderName + 'Mesh' ) | |
cylinderMesh.InitControlPoints( facets * 12 ) | |
index = 0 | |
for facet in range(0,facets): | |
q0 = vertices[facet*4] | |
q1 = vertices[facet*4+1] | |
q2 = vertices[facet*4+2] | |
q3 = vertices[facet*4+3] | |
# top triangle | |
cylinderMesh.SetControlPointAt( q0, index ) | |
index = index + 1 | |
cylinderMesh.SetControlPointAt( cylinderTop, index ) | |
index = index + 1 | |
cylinderMesh.SetControlPointAt( q3, index ) | |
index = index + 1 | |
# bottom triangle | |
cylinderMesh.SetControlPointAt( q1, index ) | |
index = index + 1 | |
cylinderMesh.SetControlPointAt( cylinderBottom, index ) | |
index = index + 1 | |
cylinderMesh.SetControlPointAt( q2, index ) | |
index = index + 1 | |
# left hand sidet | |
cylinderMesh.SetControlPointAt( q0, index ) | |
index = index + 1 | |
cylinderMesh.SetControlPointAt( q1, index ) | |
index = index + 1 | |
cylinderMesh.SetControlPointAt( q2, index ) | |
index = index + 1 | |
# right hand side tri | |
cylinderMesh.SetControlPointAt( q0, index ) | |
index = index + 1 | |
cylinderMesh.SetControlPointAt( q2, index ) | |
index = index + 1 | |
cylinderMesh.SetControlPointAt( q3, index ) | |
index = index + 1 | |
polygon = 0 | |
index = 0 | |
for facet in range(0,facets): | |
cylinderMesh.BeginPolygon(polygon) | |
cylinderMesh.AddPolygon(index) | |
cylinderMesh.AddPolygon(index+1) | |
cylinderMesh.AddPolygon(index+2) | |
cylinderMesh.EndPolygon() | |
polygon = polygon + 1 | |
index = index + 3 | |
cylinderMesh.BeginPolygon(polygon) | |
cylinderMesh.AddPolygon(index) | |
cylinderMesh.AddPolygon(index+1) | |
cylinderMesh.AddPolygon(index+2) | |
cylinderMesh.EndPolygon() | |
polygon = polygon + 1 | |
index = index + 3 | |
cylinderMesh.BeginPolygon(polygon) | |
cylinderMesh.AddPolygon(index) | |
cylinderMesh.AddPolygon(index+1) | |
cylinderMesh.AddPolygon(index+2) | |
cylinderMesh.EndPolygon() | |
polygon = polygon + 1 | |
index = index + 3 | |
cylinderMesh.BeginPolygon(polygon) | |
cylinderMesh.AddPolygon(index) | |
cylinderMesh.AddPolygon(index+1) | |
cylinderMesh.AddPolygon(index+2) | |
cylinderMesh.EndPolygon() | |
polygon = polygon + 1 | |
index = index + 3 | |
return cylinderMesh | |
def makeCube( pScene, cubeName ): | |
# A set of vertices which we will use to create a cube in the scene. | |
cubeVertices = [ fbx.FbxVector4( -1, -1, 1 ), # 0 - vertex index. | |
fbx.FbxVector4( 1, -1, 1 ), # 1 | |
fbx.FbxVector4( 1, 1, 1 ), # 2 | |
fbx.FbxVector4( -1, 1, 1 ), # 3 | |
fbx.FbxVector4( -1, -1, -1 ), # 4 | |
fbx.FbxVector4( 1, -1, -1 ), # 5 | |
fbx.FbxVector4( 1, 1, -1 ), # 6 | |
fbx.FbxVector4( -1, 1, -1 )] # 7 | |
# The polygons (faces) of the cube. | |
polygonVertices = [ ( 0, 1, 2, 3 ), # Face 1 - composed of the vertex index sequence: 0, 1, 2, and 3. | |
( 4, 5, 6, 7 ), # Face 2 | |
( 8, 9, 10, 11 ), # Face 3 | |
( 12, 13, 14, 15 ), # Face 4 | |
( 16, 17, 18, 19 ), # Face 5 | |
( 20, 21, 22, 23 )] # Face 6 | |
cubeMesh = fbx.FbxMesh.Create( pScene, cubeName + 'Mesh' ) | |
# Define the new mesh's control points. Since we are defining a cubic mesh, | |
# there are 4 control points per face, and there are six faces, for a total | |
# of 24 control points. | |
cubeMesh.InitControlPoints( 24 ) | |
# Face 1 | |
cubeMesh.SetControlPointAt( cubeVertices[0], 0 ) | |
cubeMesh.SetControlPointAt( cubeVertices[1], 1 ) | |
cubeMesh.SetControlPointAt( cubeVertices[2], 2 ) | |
cubeMesh.SetControlPointAt( cubeVertices[3], 3 ) | |
# Face 2 | |
cubeMesh.SetControlPointAt( cubeVertices[1], 4 ) | |
cubeMesh.SetControlPointAt( cubeVertices[5], 5 ) | |
cubeMesh.SetControlPointAt( cubeVertices[6], 6 ) | |
cubeMesh.SetControlPointAt( cubeVertices[2], 7 ) | |
# Face 3 | |
cubeMesh.SetControlPointAt( cubeVertices[5], 8 ) | |
cubeMesh.SetControlPointAt( cubeVertices[4], 9 ) | |
cubeMesh.SetControlPointAt( cubeVertices[7], 10 ) | |
cubeMesh.SetControlPointAt( cubeVertices[6], 11 ) | |
# Face 4 | |
cubeMesh.SetControlPointAt( cubeVertices[4], 12 ) | |
cubeMesh.SetControlPointAt( cubeVertices[0], 13 ) | |
cubeMesh.SetControlPointAt( cubeVertices[3], 14 ) | |
cubeMesh.SetControlPointAt( cubeVertices[7], 15 ) | |
# Face 5 | |
cubeMesh.SetControlPointAt( cubeVertices[3], 16 ) | |
cubeMesh.SetControlPointAt( cubeVertices[2], 17 ) | |
cubeMesh.SetControlPointAt( cubeVertices[6], 18 ) | |
cubeMesh.SetControlPointAt( cubeVertices[7], 19 ) | |
# Face 6 | |
cubeMesh.SetControlPointAt( cubeVertices[1], 20 ) | |
cubeMesh.SetControlPointAt( cubeVertices[0], 21 ) | |
cubeMesh.SetControlPointAt( cubeVertices[4], 22 ) | |
cubeMesh.SetControlPointAt( cubeVertices[5], 23 ) | |
# Now that the control points per polygon have been defined, we can create | |
# the actual polygons within the mesh. | |
for i in range( 0, len( polygonVertices ) ): | |
cubeMesh.BeginPolygon( i ) | |
for j in range( 0, len( polygonVertices[i] ) ): | |
cubeMesh.AddPolygon( polygonVertices[i][j] ) | |
cubeMesh.EndPolygon() | |
return cubeMesh | |
def addNode( pScene, nodeName, **kwargs ): | |
# Obtain a reference to the scene's root node. | |
scaling = kwargs["scaling"] | |
location = kwargs["location"] | |
newNode = fbx.FbxNode.Create( pScene, nodeName ) | |
newNode.LclScaling.Set(fbx.FbxDouble3(scaling[0], scaling[1], scaling[2])) | |
newNode.LclTranslation.Set(fbx.FbxDouble3(location[0], location[1], location[2])) | |
# Create a new node in the scene. | |
return newNode | |
def addCube( pScene, cubeName, **kwargs ): | |
''' Adds a cubic mesh to the scene. ''' | |
cubeLocation = (0.0, 0.0, 0.0) | |
cubeScale = (1.0, 1.0, 1.0) | |
if kwargs.has_key("location"): | |
cubeLocation = kwargs["location"] | |
if kwargs.has_key("scale"): | |
cubeScale = kwargs["scale"] | |
rootNode = pScene.GetRootNode() | |
newNode = addNode(pScene, cubeName, scaling = cubeScale, location = cubeLocation) | |
rootNode.AddChild( newNode ) | |
# Create a new mesh node attribute in the scene, and set it as the new node's attribute | |
newMesh = makeCube( pScene, cubeName ) | |
newNode.SetNodeAttribute( newMesh ) | |
return newNode | |
def addCylinder( pScene, cylinderName, cylinderHeight, cylinderRadius, **kwargs ): | |
cylinderLocation = (0.0, 0.0, 0.0) | |
cylinderScale = (1.0, 1.0, 1.0) | |
if kwargs.has_key("location"): | |
cylinderLocation = kwargs["location"] | |
if kwargs.has_key("scale"): | |
cylinderScale = kwargs["scale"] | |
rootNode = pScene.GetRootNode() | |
newNode = addNode(pScene, cylinderName, scaling = cylinderScale, location = cylinderLocation) | |
rootNode.AddChild( newNode ) | |
newMesh = makeCylinder( pScene, cylinderName, cylinderHeight, cylinderRadius ) | |
newNode.SetNodeAttribute( newMesh ) | |
return newNode | |
def getASCIIFormatIndex( pManager ): | |
''' Obtain the index of the ASCII export format. ''' | |
# Count the number of formats we can write to. | |
numFormats = pManager.GetIOPluginRegistry().GetWriterFormatCount() | |
# Set the default format to the native binary format. | |
formatIndex = pManager.GetIOPluginRegistry().GetNativeWriterFormat() | |
# Get the FBX format index whose corresponding description contains "ascii". | |
for i in range( 0, numFormats ): | |
# First check if the writer is an FBX writer. | |
if pManager.GetIOPluginRegistry().WriterIsFBX( i ): | |
# Obtain the description of the FBX writer. | |
description = pManager.GetIOPluginRegistry().GetWriterFormatDescription( i ) | |
# Check if the description contains 'ascii'. | |
if 'ascii' in description: | |
formatIndex = i | |
break | |
# Return the file format. | |
return formatIndex | |
def saveScene( pFilename, pFbxManager, pFbxScene, pAsASCII=False ): | |
''' Save the scene using the Python FBX API ''' | |
exporter = fbx.FbxExporter.Create( pFbxManager, '' ) | |
if pAsASCII: | |
#DEBUG: Initialize the FbxExporter object to export in ASCII. | |
asciiFormatIndex = getASCIIFormatIndex( pFbxManager ) | |
isInitialized = exporter.Initialize( pFilename, asciiFormatIndex ) | |
else: | |
isInitialized = exporter.Initialize( pFilename ) | |
if( isInitialized == False ): | |
raise Exception( 'Exporter failed to initialize. Error returned: ' + str( exporter.GetLastErrorString() ) ) | |
exporter.Export( pFbxScene ) | |
exporter.Destroy() | |
if __name__ == "__main__": | |
global fbxManager | |
sceneName = "cubeScene" | |
if (len(sys.argv) >= 2): | |
sceneName = sys.argv[1] | |
else: | |
cylinderName = "Cylinder" | |
if (len(sys.argv) >= 3): | |
cubeName = sys.argv[2] | |
fbxManager = fbx.FbxManager.Create() | |
fbxScene = fbx.FbxScene.Create( fbxManager, '' ) | |
cylinderNode = addCylinder( fbxScene, cylinderName, 300.0, 100.0 ) | |
cylinderMaterial = makeMaterial( fbxScene, cylinderName + "_Material", | |
ambient = (1.0, 0.0, 0.0), | |
diffuse = (0.0, 0.0, 1.0) ) | |
cylinderNode.AddMaterial(cylinderMaterial) | |
saveScene( sceneName + ".fbx", fbxManager, fbxScene, True) | |
fbxManager.Destroy() | |
del fbxScene | |
del fbxManager |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment