def _writeSimplex(oarch, name, jsString, faces, counts, newShapes, pBar=None): ''' Separate the writer from oarch creation so garbage collection *hopefully* works as expected ''' par = OXform(oarch.getTop(), name) props = par.getSchema().getUserProperties() prop = OStringProperty(props, "simplex") prop.setValue(str(jsString)) abcMesh = OPolyMesh(par, name) schema = abcMesh.getSchema() if pBar is not None: pBar.setLabelText('Writing Corrected Simplex') pBar.setMaximum(len(newShapes)) for i, newShape in enumerate(newShapes): if pBar is not None: pBar.setValue(i) QApplication.processEvents() else: print "Writing {0: 3d} of {1}\r".format(i, len(newShapes)), verts = mkSampleVertexPoints(newShape) abcSample = OPolyMeshSchemaSample(verts, faces, counts) schema.set(abcSample) if pBar is None: print "Writing {0: 3d} of {1}".format(len(newShapes), len(newShapes))
def toSMPX(self, path): defDict = self.toJSON() jsString = json.dumps(defDict) arch = OArchive(str(path)) # alembic does not like unicode filepaths try: par = OXform(arch.getTop(), str(self.name)) props = par.getSchema().getUserProperties() prop = OStringProperty(props, "simplex") prop.setValue(str(jsString)) mesh = OPolyMesh(par, str(self.name)) faces = Int32TPTraits.arrayType(len(self._faces)) for i, f in enumerate(self._faces): faces[i] = f counts = Int32TPTraits.arrayType(len(self._counts)) for i, c in enumerate(self._counts): counts[i] = c schema = mesh.getSchema() for shape in self.shapes: verts = shape.toSMPX() abcSample = OPolyMeshSchemaSample(verts, faces, counts) schema.set(abcSample) except: raise finally: del arch
def writeStringProperty(props, key, value, ogawa): ''' Write the definition string to an alembic OObject HDF5 (which we must still support) has a character limit to string properties. Splitting the string must be handled in a uniform way, so this function must be used Parameters ---------- props : OCompoundProperty The alembic OObject properties value : str The simplex definition string ogawa : bool If the output is ogawa ''' if len(value) > 65000 and not ogawa: value = str(value) numChunks = (len(value) // 65000) + 1 chunkSize = (len(value) // numChunks) + 1 for c in range(numChunks): prop = OStringProperty(props, "{0}{1}".format(key, c)) prop.setValue(value[chunkSize*c:chunkSize*(c+1)]) else: prop = OStringProperty(props, str(key)) prop.setValue(str(value))
def exportUnsub(inPath, outPath, newFaces, kept, shapePrefix=None, pBar=None): ''' Export the unsubdivided simplex ''' iarch = IArchive(str(inPath)) # because alembic hates unicode top = iarch.getTop() ixfo = IXform(top, top.children[0].getName()) iprops = ixfo.getSchema().getUserProperties() iprop = iprops.getProperty("simplex") jsString = iprop.getValue() if shapePrefix is not None: d = json.loads(jsString) if d['encodingVersion'] > 1: for shape in d['shapes']: shape['name'] = shapePrefix + shape['name'] else: d['shapes'] = [shapePrefix + i for i in d['shapes']] jsString = json.dumps(d) imesh = IPolyMesh(ixfo, ixfo.children[0].getName()) verts = getSampleArray(imesh) verts = verts[:, kept] indices = [] counts = [] for f in newFaces: indices.extend(f) counts.append(len(f)) abcCounts = mkArray(IntArray, counts) abcIndices = mkArray(IntArray, indices) # `False` for HDF5 `True` for Ogawa oarch = OArchive(str(outPath), False) oxfo = OXform(oarch.getTop(), ixfo.getName()) oprops = oxfo.getSchema().getUserProperties() oprop = OStringProperty(oprops, "simplex") oprop.setValue(str(jsString)) omesh = OPolyMesh(oxfo, imesh.getName()) osch = omesh.getSchema() if pBar is not None: pBar.setValue(0) pBar.setMaximum(len(verts)) pBar.setLabelText("Exporting Unsubdivided Shapes") QApplication.processEvents() for i, v in enumerate(verts): if pBar is not None: pBar.setValue(i) QApplication.processEvents() else: print "Exporting Unsubdivided Shape {0: <4}\r".format(i + 1), sample = OPolyMeshSchemaSample(mkSampleVertexPoints(v), abcIndices, abcCounts) osch.set(sample) if pBar is None: print "Exporting Unsubdivided Shape {0: <4}".format(len(verts))
def _writeSimplex(oarch, name, jsString, faces, counts, newShapes): par = OXform(oarch.getTop(), name) props = par.getSchema().getUserProperties() prop = OStringProperty(props, "simplex") prop.setValue(str(jsString)) abcMesh = OPolyMesh(par, name) schema = abcMesh.getSchema() for i, newShape in enumerate(newShapes): print "Writing {0: 3d} of {1}\r".format(i, len(newShapes)), abcSample = OPolyMeshSchemaSample(newShape, faces, counts) schema.set(abcSample) print "Writing {0: 3d} of {1}".format(len(newShapes), len(newShapes))
def exportABC(self, path): defDict = self.simplex.buildDefinition() jsString = json.dumps(defDict) arch = OArchive(str(path)) # alembic does not like unicode filepaths try: par = OXform(arch.getTop(), str(self.name)) props = par.getSchema().getUserProperties() prop = OStringProperty(props, "simplex") prop.setValue(str(jsString)) mesh = OPolyMesh(par, str(self.name)) self.DCC.exportABC(mesh, defDict) finally: del arch
def _writeSimplex(oarch, name, jsString, faces, counts, newShapes): ''' Separate the writer from oarch creation so garbage collection *hopefully* works as expected ''' par = OXform(oarch.getTop(), name) props = par.getSchema().getUserProperties() prop = OStringProperty(props, "simplex") prop.setValue(str(jsString)) abcMesh = OPolyMesh(par, name) schema = abcMesh.getSchema() for i, newShape in enumerate(newShapes): print "Writing {0: 3d} of {1}\r".format(i, len(newShapes)), abcSample = OPolyMeshSchemaSample(newShape, faces, counts) schema.set(abcSample) print "Writing {0: 3d} of {1}".format(len(newShapes), len(newShapes))
def extractExternal(self, path, dccMesh): # Extract shapes from an arbitrary mesh based on the current simplex defDict = self.simplex.buildDefinition() jsString = json.dumps(defDict) arch = OArchive(str(path)) # alembic does not like unicode filepaths try: par = OXform(arch.getTop(), str(self.name)) props = par.getSchema().getUserProperties() prop = OStringProperty(props, "simplex") prop.setValue(str(jsString)) abcMesh = OPolyMesh(par, str(self.name)) self.DCC.exportABC(dccMesh, abcMesh, defDict) finally: del arch
def _exportAbc(arch, smpx, shapeArray, faces, counts, uvs): par = OXform(arch.getTop(), str(smpx.name)) props = par.getSchema().getUserProperties() prop = OStringProperty(props, "simplex") prop.setValue(str(smpx.dump())) abcMesh = OPolyMesh(par, str(smpx.name)) schema = abcMesh.getSchema() for i in range(len(smpx.shapes)): if uvs is not None: abcSample = OPolyMeshSchemaSample( mkSampleVertexPoints(shapeArray[i]), faces, counts, uvs) else: # can't just pass uvs as None because of how the Alembic API works abcSample = OPolyMeshSchemaSample( mkSampleVertexPoints(shapeArray[i]), faces, counts) schema.set(abcSample)
def toSMPX(self, path, pBar=None): defDict = self.toJSON() jsString = json.dumps(defDict) # `False` for HDF5 `True` for Ogawa arch = OArchive(str(path), False) # alembic does not like unicode filepaths try: par = OXform(arch.getTop(), str(self.name)) props = par.getSchema().getUserProperties() prop = OStringProperty(props, "simplex") prop.setValue(str(jsString)) mesh = OPolyMesh(par, str(self.name)) faces = Int32TPTraits.arrayType(len(self._faces)) for i, f in enumerate(self._faces): faces[i] = f counts = Int32TPTraits.arrayType(len(self._counts)) for i, c in enumerate(self._counts): counts[i] = c schema = mesh.getSchema() if pBar is not None: pBar.setMaximum(len(self.shapes)) pBar.setValue(0) pBar.setLabelText("Exporting Split Shapes") QApplication.processEvents() for i, shape in enumerate(self.shapes): if pBar is not None: pBar.setValue(i) QApplication.processEvents() else: print "Exporting Shape {0} of {1}\r".format(i+1, len(self.shapes)), verts = shape.toSMPX() abcSample = OPolyMeshSchemaSample(verts, faces, counts) schema.set(abcSample) if pBar is None: print except: raise finally: del arch
def _exportUnsub(outPath, xfoName, meshName, jsString, faces, verts, uvFaces, uvs, pBar=None): oarch = OArchive(str(outPath), OGAWA) # False for HDF5 oxfo = OXform(oarch.getTop(), xfoName) oprops = oxfo.getSchema().getUserProperties() oprop = OStringProperty(oprops, "simplex") oprop.setValue(str(jsString)) omesh = OPolyMesh(oxfo, meshName) osch = omesh.getSchema() if pBar is not None: pBar.setValue(0) pBar.setMaximum(len(verts)) pBar.setLabelText("Exporting Unsubdivided Shapes") QApplication.processEvents() abcIndices = mkSampleIntArray(list(chain.from_iterable(faces))) abcCounts = mkSampleIntArray(map(len, faces)) kwargs = {} if uvs is not None: # Alembic doesn't use None as the placeholder for un-passed kwargs # So I don't have to deal with that, I only set the kwarg dict if the uvs exist uvidx = None if uvFaces is None else list(chain.from_iterable(uvFaces)) uvSample = mkUvSample(uvs, uvidx) kwargs['iUVs'] = uvSample for i, v in enumerate(verts): pbPrint(pBar, "Exporting Unsubdivided Shape", i) sample = OPolyMeshSchemaSample(mkSampleVertexPoints(v), abcIndices, abcCounts, **kwargs) osch.set(sample) pbPrint(pBar, "Done")
def buildAbc(outPath, points, faces, faceCounts=None, uvs=None, uvFaces=None, normals=None, normFaces=None, name='polymsh', shapeSuffix='Shape', transformSuffix='', propDict=None): ''' Build a single-mesh alembic file from all of the non-alembic raw data Parameters ---------- outPath: str or OArchive The output path for the alembic file points: list or ndarray The list or array of points. Single multiple frames supported faces: list A list of lists of face indices, or a flattened list of indices. If flat, then faceCounts must be provided faceCounts: list A list of the number of vertices per face. Defaults to None uvs: list or ndarray The Uvs for this mesh. Defaults to None uvFaces: list A list of lists of face indices, or a flattened list of indices. If flat, then faceCounts must be provided. Defaults to None normals: list or ndarray The Normals for this mesh. Defaults to None normFaces: list A list of lists of face indices, or a flattened list of indices. If flat, then faceCounts must be provided. Defaults to None name: str The name to give this mesh. Defaults to "polymsh" shapeSuffix: str The suffix to add to the shape of this mesh. Defaults to "Shape" transformSuffix: str The suffix to add to the transform of this mesh. Defaults to "" propDict: dict A dictionary of properties to add to the xform object ''' if faceCounts is None: # All the faces are in list-of-list format # put them in index-count format faceCounts, faces = _flattenFaces(faces) if uvFaces is not None: _, uvFaces = _flattenFaces(uvFaces) if normFaces is not None: _, normFaces = _flattenFaces(normFaces) faceCounts = mkSampleIntArray(faceCounts) faces = mkSampleIntArray(faces) if uvFaces is not None and uvs is not None: uvs = mkUvSample(uvs, indexes=uvFaces) if normFaces is not None and normals is not None: normals = mkNormalSample(normals, indexes=normFaces) if isinstance(outPath, basestring): oarch = OArchive(str(outPath), False) #False for HDF5 else: oarch = outPath parent = oarch.getTop() opar = OXform(parent, name + transformSuffix) if propDict: props = opar.getSchema().getUserProperties() for k, v in propDict.iteritems(): prop = OStringProperty(props, str(k)) prop.setValue(str(v)) omesh = OPolyMesh(opar, name + shapeSuffix) if np is not None: points = np.array(points) if len(points.shape) == 2: points = points[None, ...] else: if not isinstance(points[0][0], (list, tuple)): points = [points] sch = omesh.getSchema() for frame in points: abcFrame = mkSampleVertexPoints(frame) setAlembicSample(sch, abcFrame, faces, faceCounts, uvs=uvs, normals=normals) return oarch