http://cgkit.sourceforge.net/tutorials/code_examples/shownormals.html
Visualizing vertex positions and normals Author: Matthias Baas (baas@ira.uka.de) Date: 2004/12/20
This code example shows the following things:
- How to iterate over all objects in the scene
- How to iterate over mesh vertices and faces
- How to access primitive variables such as normals
- How to process the two storage types "varying" vs "user"/"uniform int XYZfaces?[3]?"
- How to draw 3D marker and lines
http://cgkit.sourceforge.net/tutorials/code_examples/shownormals_screenshot.jpg
The following script loads a scene and shows the vertices and normals of every mesh in the scene. The vertices are displayed as blue markers and the normals as lines.
shownormals_screenshot.jpg
Here is the script and a demo file (bunny.3ds) containing the Stanford Bunny. ###################################################################### # Visualizing the vertices and normals of a triangle mesh # # This script loads a scene and shows the vertices and normals of # every mesh in the scene. # # Invoke the script via the viewer tool: # $ viewer.py shownormals.py ######################################################################
def showVertices(mesh): """Draw markers at the vertex positions of a triangle mesh. """
# Vertices are stored in the local coordinate system of the geometry. # But as we need the coordinates relative to the world coordinate # system we have to obtain the transformation L that transforms from # local to world coordinates. L = mesh.worldtransform
# Iterate over the vertices and draw a marker at the global vertex # position Lv. for v in mesh.verts: drawMarker(Lv, size=0.07, color=(0,0,1))
def showNormals(mesh): """Draw the normals as lines.
A normal is drawn at every vertex position. The normals may either be specified as "varying normal N" or as "user normal N"/"uniform int Nfaces[3]?". The actual drawing code is in showVaryingNormals() and showUserNormals(). """
# Check if there are normals available in this mesh desc = mesh.findVariable("N") if desc==None: print 'Mesh "%s" has no normals set.'%mesh.name return
# Unpack the variable descriptor name, storage_class, type, mult = desc
# Are the normals stored as "varying normal N"? if storage_class==VARYING and type==NORMAL and mult==1: showVaryingNormals(mesh)
# Or are they stored as "user normal N"? elif storage_class==USER and type==NORMAL and mult==1: # Check if the normal faces are available desc = mesh.findVariable("Nfaces") if desc==None: print 'Mesh "%s" has no normal faces set.'%mesh.name else: name, storage_class, type, mult = desc if storage_class==UNIFORM and type==INT and mult==3: # "N" and "Nfaces" is available and of the right type... showUserNormals(mesh) else: print 'Mesh "%s": Invalid declaration of "Nfaces"'%mesh.name
else: print 'Mesh "%s": Invalid declaration of variable "N".'%mesh.name
def showVaryingNormals(mesh): """Draw normals given as "varying normal N". """ # Get the world transform to transform the local vertices and normals # into the world coordinate system L = mesh.worldtransform L0 = Lvec3(0) # Obtain the slot carrying the normals N = mesh.geom.slot("N") # Iterate over the faces and draw the vertices and normals for i,j,k in mesh.faces: a = Lmesh.verts[i]? b = L*mesh.verts[j]? c = L*mesh.verts[k]? na = L*N[i]?-L0 nb = L*N[j]?-L0 nc = L*N[k]?-L0 drawLine(a, a+na) drawLine(b, b+nb) drawLine(c, c+nc)
def showUserNormals(mesh): """Draw normals given as "user normal N"/"uniform int Nfaces[3]?". """ # Get the world transform to transform the local vertices and normals # into the world coordinate system L = mesh.worldtransform L0 = Lvec3(0) # Obtain the slot carrying the normals and the normal faces N = mesh.geom.slot("N") Nfaces = mesh.geom.slot("Nfaces") # Iterate over the faces and normal faces... for face, Nface in zip(mesh.faces, Nfaces): i,j,k = face ni,nj,nk = Nface a = Lmesh.verts[i]? b = L*mesh.verts[j]? c = L*mesh.verts[k]? na = L*N[ni]?-L0 nb = L*N[nj]?-L0 nc = L*N[nk]?-L0 drawLine(a, a+na) drawLine(b, b+nb) drawLine(c, c+nc)
######################################################################
# Load a scene file load("bunny.3ds")
# Show its contents listWorld()
# Draw the vertices & normals of every triangle mesh in the scene for obj in scene.walkWorld(): # Check if the object is a triangle mesh if isinstance(obj.geom, TriMeshGeom?): # Uncomment the following line to convert the normals from # "user normal" to "varying normal" # obj.geom = convMeshAttr(obj.geom, "N") print 'Creating vertex markers for "%s"...'%obj.name showVertices(obj) print 'Creating normal lines for "%s"...'%obj.name showNormals(obj)
Back to the tutorial index