Getting Started: Simple Wrapping¶
Start with importing module wrap
import wrap
Loading Geometry¶
Load basemesh from file. The default folder for wrap’s example models is stored in wrap.demoModelsPath
basemeshFileName = wrap.openFileDialog("Select Basemesh",filter = "OBJ-file (*.obj)",dir = wrap.demoModelsPath)
basemesh = wrap.Geom(basemeshFileName)
Load scan.
Note
If scan is in small scale it is highly recommended to pre-scale the model with some reasonable scaleFactor.
scanFileName = wrap.openFileDialog("Select Scan",filter = "OBJ-file (*.obj)",dir = wrap.demoModelsPath)
scan = wrap.Geom(scanFileName,scaleFactor = 1000)
Turn off wireframe
scan.wireframe = False
Load scan’s texture
textureFileName = wrap.openFileDialog("Select Scan's Texture",filter = "Image (*.jpg *.png *.bmp *.tga)",dir = wrap.demoModelsPath)
if textureFileName is not None:
scan.texture = wrap.Image(textureFileName)
Show texture in 2D-viewport
scan.texture.show()
Pre-Alignment¶
If the basemesh and the scan are in different scale and orientation we need to pre-align them using rigidAlignment. At least 3 user-defined point correspondences are required to find affine transformation between the basemesh and the scan
# display point selection dialog
(pointsScan, pointsBasemesh) = wrap.selectPoints(scan,basemesh)
# find rigid alignment transformation as matrix 4x4
rigidTransformation = wrap.rigidAlignment(basemesh,pointsBasemesh,scan,pointsScan,matchScale = True)
# apply the transformation to the basemesh
basemesh.transform(rigidTransformation)
basemesh.fitToView()
Non-Rigid Registration¶
Now that the basemesh and the scan are pre-aligned we can start non-rigid registration. The user can help the registration process by providing several user-defined point correspondences. In some cases you don’t want some polygons of the basemesh to be stitched to the scan. For example when an actor has a stocking on his head. Wrapping the back side of basemesh’s head around the stocking would make no sense as the stocking’s shape does not reflects the real shape of the actor’s head. In this situation it’s better to leave correspondent polygons of the basemesh as less affected as possible. All you need it to select correspondent polygons of the basemesh as Free polygons
# display point selection dialog to define point correspondences
(controlPointsScan,controlPointsBasemesh) = wrap.selectPoints(scan,basemesh)
# display polygon selection dialog to define free polygons
freePolygonsBasemesh = wrap.selectPolygons(basemesh)
# start non-rigid registration
basemesh = wrap.nonRigidRegistration(basemesh,scan,controlPointsBasemesh,controlPointsScan,freePolygonsBasemesh,minNodes = 15,initialRadiusMultiplier = 1.0,smoothnessFinal = 0.1,maxIterations = 20)
Extracting Details¶
Now that the basemesh is wrapped around the scan you might want to extract more small details from the scan. In order to do that you can subdivide the basemesh and to project it onto the scan
# subdivide
basemesh = wrap.subdivide(basemesh)
# project
disabledPolygons = wrap.selectPolygons(basemesh)
basemesh = wrap.projectMesh(basemesh,scan,maxRelativeDist = 1,disabledPolygonIndicesSrc = disabledPolygons)
Transferring Texture¶
If the scan has texture we can project it to the basemesh
if scan.texture is not None:
basemesh.texture = wrap.transferTexture(scan,scan.texture,basemesh,(2048,2048),maxRelativeDist = 3)
# fill holes on the texture by color extrapolation. This is useful for hiding texture seams.
basemesh.texture.extrapolate()
Saving Results¶
Now that we have our final model we can save the model and the texture to file
basemesh.save("wrapped.obj",scaleFactor = 1.0 / scaleFactor)
if scan.texture is not None:
basemesh.texture.save("wrapped.jpg")