Skip to content

Instantly share code, notes, and snippets.

@johnfredcee
Created October 29, 2012 18:05
Show Gist options
  • Save johnfredcee/3975322 to your computer and use it in GitHub Desktop.
Save johnfredcee/3975322 to your computer and use it in GitHub Desktop.
FBX Python SDK sample cube and cylinder
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