def drawPlanes(self, skel): def _get_face_count(skel): result = 0 for bone in skel.getBones(): if isinstance(bone.roll, list): result += len(bone.roll) else: result += 1 return result import module3d self.planesMesh = module3d.Object3D("SkeletonPlanesMesh", 3) facecount = _get_face_count(skel) vertcount = 3 * facecount faces = np.arange(vertcount, dtype=np.uint16).reshape((facecount, 3)) verts = np.zeros((vertcount, 3), dtype=np.float32) vcolors = 255 * np.ones((vertcount, 4), dtype=np.uint8) PLANE_COLORS = [[60, 230, 200], [220, 60, 230], [230, 180, 60], [230, 90, 60], [60, 230, 60], [60, 120, 230]] fgroups = np.zeros(len(faces), dtype=np.uint16) v_offset = 0 for bIdx, bone in enumerate(skel.getBones()): fg = self.planesMesh.createFaceGroup(bone.name) fgroups[bIdx:bIdx + 1] = np.repeat( np.array(fg.idx, dtype=np.uint16), 1) if isinstance(bone.roll, list): for p_idx, plane_name in enumerate(bone.roll): plane_name = bone.roll[0] plane_joints = bone.planes[plane_name] j1, j2, j3 = plane_joints in_rest = False p1 = skel.getJointPosition(j1, self.human, in_rest)[:3] * skel.scale p2 = skel.getJointPosition(j2, self.human, in_rest)[:3] * skel.scale p3 = skel.getJointPosition(j3, self.human, in_rest)[:3] * skel.scale verts[v_offset:v_offset + 3] = [p1, p2, p3] vcolors[v_offset:v_offset + 3, :3] = PLANE_COLORS[p_idx] fgroups[v_offset // 3] = fg.idx v_offset += 3 elif isinstance(bone.roll, str): plane_name = bone.roll plane_joints = bone.planes[plane_name] j1, j2, j3 = plane_joints in_rest = False p1 = skel.getJointPosition(j1, self.human, in_rest)[:3] * skel.scale p2 = skel.getJointPosition(j2, self.human, in_rest)[:3] * skel.scale p3 = skel.getJointPosition(j3, self.human, in_rest)[:3] * skel.scale verts[v_offset:v_offset + 3] = [p1, p2, p3] vcolors[v_offset:v_offset + 3, :3] = PLANE_COLORS[0] fgroups[v_offset // 3] = fg.idx v_offset += 3 else: p1 = p2 = p3 = [0.0, 0.0, 0.0] verts[v_offset:v_offset + 3] = [p1, p2, p3] vcolors[v_offset:v_offset + 3, :3] = [255, 0, 0] fgroups[v_offset // 3] = fg.idx v_offset += 3 self.planesMesh.setCoords(verts) self.planesMesh.setColor(vcolors) self.planesMesh.setUVs(np.zeros( (1, 2), dtype=np.float32)) # Set trivial UV coordinates self.planesMesh.setFaces(faces, None, fgroups) self.planesMesh.updateIndexBuffer() self.planesMesh.calcNormals() self.planesMesh.update() self.planesMesh.setCameraProjection(0) self.planesMesh.priority = 100 self.planesMesh.setPickable(False) self.planesObj = self.addObject( gui3d.Object(self.planesMesh, self.human.getPosition())) self.planesObj.setShadeless(0) self.planesObj.setSolid(0) self.planesObj.setRotation(self.human.getRotation()) self.planesObj.material.backfaceCull = False self.planesObj.setVisibility(self.showPlanesTggl.selected)
def loadObjFile(path, obj=None): """ Parse and load a Wavefront OBJ file as mesh. Parser does not support normals, and assumes all objects should be smooth shaded. Use duplicate vertices for achieving hard edges. """ if obj == None: name = os.path.splitext(os.path.basename(path))[0] obj = module3d.Object3D(name) objFile = open(path, 'rU', encoding="utf-8") fg = None mtl = None verts = [] uvs = [] fverts = [] fuvs = [] groups = [] has_uv = False materials = {} faceGroups = {} for objData in objFile: lineData = objData.split() if len(lineData) > 0: command = lineData[0] # Vertex coordinate if command == 'v': verts.append((float(lineData[1]), float(lineData[2]), float(lineData[3]))) # Vertex texture (UV) coordinate elif command == 'vt': uvs.append((float(lineData[1]), float(lineData[2]))) # Face definition (reference to vertex attributes) elif command == 'f': if not fg: if 0 not in faceGroups: faceGroups[0] = obj.createFaceGroup( 'default-dummy-group') fg = faceGroups[0] uvIndices = [] vIndices = [] for faceData in lineData[1:]: vInfo = faceData.split('/') vIdx = int(vInfo[0]) - 1 # -1 because obj is 1 based list vIndices.append(vIdx) # If there are other data (uv, normals, etc) if len(vInfo) > 1 and vInfo[1] != '': uvIndex = int( vInfo[1]) - 1 # -1 because obj is 1 based list uvIndices.append(uvIndex) if len(vIndices) == 3: vIndices.append(vIndices[0]) fverts.append(tuple(vIndices)) if len(uvIndices) > 0: if len(uvIndices) == 3: uvIndices.append(uvIndices[0]) has_uv = True if len(uvIndices) < 4: uvIndices = [0, 0, 0, 0] fuvs.append(tuple(uvIndices)) groups.append(fg.idx) elif command == 'g': fgName = lineData[1] if fgName not in faceGroups: faceGroups[fgName] = obj.createFaceGroup(fgName) fg = faceGroups[fgName] elif command == 'usemtl': pass # ignore materials elif command == 'o': obj.name = lineData[1] objFile.close() # Sanity check for loose vertices strayVerts = [] referencedVerts = set([v for fvert in fverts for v in fvert]) for vIdx in range(len(verts)): if vIdx not in referencedVerts: strayVerts.append(vIdx) if len(strayVerts) > 0: import log msg = "Error loading OBJ file %s: Contains loose vertices, not connected to a face (%s)" log.error(msg, path, strayVerts) raise RuntimeError(msg % (path, strayVerts)) obj.setCoords(verts) obj.setUVs(uvs) obj.setFaces(fverts, fuvs if has_uv else None, groups) obj.calcNormals() obj.updateIndexBuffer() return obj
def __init__(self, category): gui3d.TaskView.__init__(self, category, 'Measure') self.ruler = Ruler() self.measureMesh = module3d.Object3D('measure', 2) self.measureMesh.createFaceGroup('measure') names = [] for n, v in self.ruler.Measures.items(): if len(v) % 2 != 0: names.append(n) if len(names) > 0: raise RuntimeError( "One or more measurement rulers contain an uneven number of vertex indices. It's required that they are pairs indicating the begin and end point of every line to draw. Rulers with uneven index count: %s" % ", ".join(names)) del names count = max([len(vertIdx) for vertIdx in self.ruler.Measures.values()]) self.measureMesh.setCoords(np.zeros((count, 3), dtype=np.float32)) self.measureMesh.setUVs(np.zeros((1, 2), dtype=np.float32)) self.measureMesh.setFaces(np.arange(count).reshape((-1, 2))) self.measureMesh.setCameraProjection(0) self.measureMesh.setShadeless(True) self.measureMesh.setDepthless(True) self.measureMesh.setColor([255, 255, 255, 255]) self.measureMesh.setPickable(0) self.measureMesh.updateIndexBuffer() self.measureMesh.priority = 50 self.measureObject = self.addObject(gui3d.Object(self.measureMesh)) measurements = [ ('neck', ['neckcirc', 'neckheight']), ('upperarm', ['upperarm', 'upperarmlenght']), ('lowerarm', ['lowerarmlenght', 'wrist']), ('torso', [ 'frontchest', 'bust', 'underbust', 'waist', 'napetowaist', 'waisttohip', 'shoulder' ]), ('hips', ['hips']), ('upperleg', ['upperlegheight', 'thighcirc']), ('lowerleg', ['lowerlegheight', 'calf']), ('ankle', ['ankle']), ] sliderLabel = { 'neckcirc': 'Neck circum', 'neckheight': 'Neck height', 'upperarm': 'Upper arm circum', 'upperarmlenght': 'Upperarm length', 'lowerarmlenght': 'Lowerarm length', 'wrist': 'Wrist circum', 'frontchest': 'Front chest dist', 'bust': 'Bust circum', 'underbust': 'Underbust circum', 'waist': 'Waist circum', 'napetowaist': 'Nape to waist', 'waisttohip': 'Waist to hip', 'shoulder': 'Shoulder dist', 'hips': 'Hips circum', 'upperlegheight': 'Upperleg height', 'thighcirc': 'Thigh circ.', 'lowerlegheight': 'Lowerleg height', 'calf': 'Calf circum', 'ankle': 'Ankle circum' } self.groupBoxes = {} self.radioButtons = [] self.sliders = [] self.active_slider = None self.modifiers = {} measureDataPath = mh.getSysDataPath("targets/measure/") self.categoryBox = self.addRightWidget(gui.GroupBox('Category')) self.groupBox = self.addLeftWidget(gui.StackedBox()) for name, subnames in measurements: # Create box box = self.groupBox.addWidget(gui.SliderBox(name.capitalize())) self.groupBoxes[name] = box # Create radiobutton box.radio = self.categoryBox.addWidget( GroupBoxRadioButton(self, self.radioButtons, name.capitalize(), box, selected=len(self.radioButtons) == 0)) # Create sliders for subname in subnames: # TODO use another modifier modifier = humanmodifier.Modifier( os.path.join(measureDataPath, "measure-%s-decrease.target" % subname), os.path.join(measureDataPath, "measure-%s-increase.target" % subname)) modifier.setHuman(gui3d.app.selectedHuman) self.modifiers[subname] = modifier slider = box.addWidget( MeasureSlider(sliderLabel[subname], self, subname, modifier)) self.sliders.append(slider) self.lastActive = None self.statsBox = self.addRightWidget(gui.GroupBox('Statistics')) self.height = self.statsBox.addWidget(gui.TextView('Height: ')) self.chest = self.statsBox.addWidget(gui.TextView('Chest: ')) self.waist = self.statsBox.addWidget(gui.TextView('Waist: ')) self.hips = self.statsBox.addWidget(gui.TextView('Hips: ')) ''' self.braBox = self.addRightWidget(gui.GroupBox('Brassiere size')) self.eu = self.braBox.addWidget(gui.TextView('EU: ')) self.jp = self.braBox.addWidget(gui.TextView('JP: ')) self.us = self.braBox.addWidget(gui.TextView('US: ')) self.uk = self.braBox.addWidget(gui.TextView('UK: ')) ''' self.groupBox.showWidget(self.groupBoxes['neck'])
def loadMesh(path, locX=0, locY=0, locZ=0, loadColors=1, maxFaces=None): """ This function loads the specified mesh object into internal MakeHuman data structures, and returns it. The loaded file should be in Wavefront OBJ format. Parameters: ----------- path: *String*. The file system path to the file containing the object to load. locX: *float* X location of loaded obj, default = 0 locY: *float* Y location of loaded obj, default = 0 locZ: *float* Z location of loaded obj, default = 0 Note: loadColors is currently unused maxFaces: *uint* Number of faces per vertex (pole), None for default (min 4) """ name = os.path.basename(path) obj = module3d.Object3D(name) if maxFaces: obj.MAX_FACES = maxFaces obj.path = path obj.x = locX obj.y = locY obj.z = locZ try: npzpath = os.path.splitext(path)[0] + '.npz' try: if not os.path.isfile(npzpath): log.message('compiled file missing: %s', npzpath) raise RuntimeError('compiled file missing: %s', npzpath) if os.path.isfile(path) and os.path.getmtime( path) > os.path.getmtime(npzpath): log.message('compiled file out of date: %s', npzpath) raise RuntimeError('compiled file out of date: %s', npzpath) loadBinaryMesh(obj, npzpath) except Exception as e: showTrace = not isinstance(e, RuntimeError) log.warning("Problem loading binary mesh: %s", e, exc_info=showTrace) loadTextMesh(obj, path) if isSubPath(npzpath, getPath('')): # Only write compiled binary meshes to user data path try: saveBinaryMesh(obj, npzpath) except StandardError: log.notice('unable to save compiled mesh: %s', npzpath) else: log.debug('Not writing compiled meshes to system paths (%s).', npzpath) except: log.error('Unable to load obj file: %s', path, exc_info=True) return False return obj
def loadMesh(path, loadColors=1, maxFaces=None, obj=None): """ This function loads the specified mesh object into internal MakeHuman data structures, and returns it. The loaded file should be in Wavefront OBJ format. Parameters: ----------- path: *String*. The file system path to the file containing the object to load. Note: loadColors is currently unused maxFaces: *uint* Number of faces per vertex (pole), None for default (min 4) """ if type(path) is bytes: path = path.decode('utf-8') log.debug("loadMesh in files3d received a raw path of %s", path) name = os.path.basename(path) if isinstance(name, bytes): name.decode('utf-8') log.debug("os.path.basename produce a name of: %s", name) log.debug("files3d loadMesh basename is %s", name) if obj is None: obj = module3d.Object3D(os.path.splitext(path)[0]) log.message("obj name changed from None to %s", module3d.Object3D(name)) if maxFaces: obj.MAX_FACES = maxFaces obj.path = path try: import getpath path = getpath.getSysPath(path) log.message("Expanded path is found to be %s", path) npzpath = os.path.splitext(path)[0] + '.npz' log.debug("files3d loadMesh will attempt to load %s", npzpath) if not os.path.isfile(npzpath): log.message('compiled file missing: %s', npzpath) raise RuntimeError('compiled file missing: %s', npzpath) if os.path.isfile( path) and os.path.getmtime(path) > os.path.getmtime(npzpath): log.message('compiled file out of date: %s', npzpath) raise RuntimeError('compiled file out of date: %s', npzpath) loadBinaryMesh(obj, npzpath) log.message("files3d loadMesh attempting to load %s", npzpath) loadTextMesh(obj, path) if isSubPath(npzpath, getPath('')): # Only write compiled binary meshes to user data path saveBinaryMesh(obj, npzpath) log.debug('files3d just saved compiled mesh: %s', npzpath) else: log.debug("files3d using getpath('') could not find (%s).", npzpath) except: log.error('Unable to load obj file: %s', path, exc_info=True) return False return obj