def Cylinder(col, length, radius = 0.98): sep = SoSeparator() cyl = SoCylinder() cyl.radius.setValue(radius) cyl.height.setValue(length) cyl.parts = SoCylinder.SIDES light = SoShapeHints() mat = SoMaterial() mat.emissiveColor = col mat.diffuseColor = col mat.transparency.setValue(0.5) rot = SoRotationXYZ() rot.axis = SoRotationXYZ.X rot.angle = pi / 2 trans = SoTransparencyType() # trans.value = SoTransparencyType.DELAYED_BLEND trans.value = SoTransparencyType.SORTED_OBJECT_BLEND # trans.value = SoTransparencyType.SORTED_OBJECT_SORTED_TRIANGLE_BLEND sep.addChild(light) sep.addChild(rot) sep.addChild(trans) sep.addChild(mat) sep.addChild(cyl) return sep
def main(): app = QApplication(sys.argv) root = SoSeparator() col = SoBaseColor() col.rgb = SbColor(1, 1, 0) root.addChild(col) root.addChild(SoCone()) viewer = QuarterWidget() viewer.setSceneGraph(root) viewer.setWindowTitle("minimal") viewer.show() sys.exit(app.exec_())
def build_head(self): head_separator = SoSeparator() head_separator.setName('head') self.head = SoCone() self.head_transformation = SoTransform() self.head_material = SoMaterial() self.head_material.ambientColor = (.33, .22, .27) self.head_material.diffuseColor = (.78, .57, .11) self.head_material.specularColor = (.99, .94, .81) self.head_material.shininess = .28 head_separator.addChild(self.head_material) head_separator.addChild(self.head_transformation) head_separator.addChild(self.head) return head_separator
def build_tail(self): separator = SoSeparator() separator.setName('tail') self.tail = SoSphere() self.tail.radius = default_tail_radius self.tail_transformation = SoTransform() self.tail_material = SoMaterial() self.tail_material.ambientColor = (.33, .22, .27) self.tail_material.diffuseColor = (.78, .57, .11) self.tail_material.specularColor = (.99, .94, .81) self.tail_material.shininess = .28 separator.addChild(self.tail_material) separator.addChild(self.tail_transformation) separator.addChild(self.tail) return separator
def SimpleSphere(p, radius=.05, mat=None): sep = SoSeparator() sep.setName("Sphere") tr = SoTranslation() tr.setName("Translation") sp = SoSphere() sp.radius = radius tr.translation = p if mat is None: mat = SoMaterial() mat.ambientColor.setValue(.33, .22, .27) mat.diffuseColor.setValue(.78, .57, .11) mat.specularColor.setValue(.99, .94, .81) mat.shininess = .28 sep.addChild(tr) sep.addChild(mat) sep.addChild(sp) return sep
class OpenVRTest(object): "FreeCAD OpenVR testing script" def __init__(self): self._running = True def setupscene(self): #coin3d setup vpRegion = SbViewportRegion(self.w, self.h) self.m_sceneManager = SoSceneManager() #scene manager overhead over render manager seems to be pretty #small self.m_sceneManager.setViewportRegion(vpRegion) self.m_sceneManager.setBackgroundColor(SbColor(0.0, 0.0, 0.8)) light = SoDirectionalLight() light2 = SoDirectionalLight() light2.direction.setValue(-1,-1,-1) light2.intensity.setValue(0.6) light2.color.setValue(0.8,0.8,1) self.scale = SoScale() self.scale.scaleFactor.setValue(0.001, 0.001, 0.001) #OpenVR uses meters not milimeters self.camtrans0 = SoTranslation() self.camtrans1 = SoTranslation() self.cgrp0 = SoGroup() self.cgrp1 = SoGroup() self.sgrp0 = SoGroup() self.sgrp1 = SoGroup() self.camtrans0.translation.setValue([self.camToHead[0][0][3],0,0]) self.camtrans1.translation.setValue([self.camToHead[1][0][3],0,0]) sg = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph()#get active scenegraph #LEFT EYE self.rootScene0 = SoSeparator() self.rootScene0.ref() self.rootScene0.addChild(self.cgrp0) self.cgrp0.addChild(self.camtrans0) self.cgrp0.addChild(self.camera0) self.rootScene0.addChild(self.sgrp0) self.sgrp0.addChild(light) self.sgrp0.addChild(light2) self.sgrp0.addChild(self.scale) self.sgrp0.addChild(sg)#add scenegraph #RIGHT EYE self.rootScene1 = SoSeparator() self.rootScene1.ref() self.rootScene1.addChild(self.cgrp1) self.cgrp1.addChild(self.camtrans1) self.cgrp1.addChild(self.camera1) self.rootScene1.addChild(self.sgrp1) self.sgrp1.addChild(light) self.sgrp1.addChild(light2) self.sgrp1.addChild(self.scale) self.sgrp1.addChild(sg)#add scenegraph def setupcameras(self): nearZ = self.nearZ farZ = self.farZ #LEFT EYE self.camera0 = SoFrustumCamera() self.basePosition0 = SbVec3f(0.0, 0.0, 0.0) self.camera0.position.setValue(self.basePosition0) self.camera0.viewportMapping.setValue(SoCamera.LEAVE_ALONE) left = nearZ * self.proj_raw[0][0] right = nearZ * self.proj_raw[0][1] top = nearZ * self.proj_raw[0][3] #top and bottom are reversed https://github.com/ValveSoftware/openvr/issues/110 bottom = nearZ * self.proj_raw[0][2] aspect = (top - bottom) / (right - left) self.camera0.nearDistance.setValue(nearZ) self.camera0.farDistance.setValue(farZ) self.camera0.left.setValue(left) self.camera0.right.setValue(right) self.camera0.top.setValue(top) self.camera0.bottom.setValue(bottom) self.camera0.aspectRatio.setValue(aspect) #RIGHT EYE self.camera1 = SoFrustumCamera() self.basePosition1 = SbVec3f(0.0, 0.0, 0.0) self.camera1.position.setValue(self.basePosition1) self.camera1.viewportMapping.setValue(SoCamera.LEAVE_ALONE) left = nearZ * self.proj_raw[1][0] right = nearZ * self.proj_raw[1][1] top = nearZ * self.proj_raw[1][3] bottom = nearZ * self.proj_raw[1][2] aspect = (top - bottom) / (right - left) self.camera1.nearDistance.setValue(nearZ) self.camera1.farDistance.setValue(farZ) self.camera1.left.setValue(left) self.camera1.right.setValue(right) self.camera1.top.setValue(top) self.camera1.bottom.setValue(bottom) self.camera1.aspectRatio.setValue(aspect) def extractrotation(self, transfmat): #extract rotation quaternion qw = sqrt(numpy.fmax(0, 1 + transfmat[0][0] + transfmat[1][1] + transfmat[2][2])) / 2 qx = sqrt(numpy.fmax(0, 1 + transfmat[0][0] - transfmat[1][1] - transfmat[2][2])) / 2 qy = sqrt(numpy.fmax(0, 1 - transfmat[0][0] + transfmat[1][1] - transfmat[2][2])) / 2 qz = sqrt(numpy.fmax(0, 1 - transfmat[0][0] - transfmat[1][1] + transfmat[2][2])) / 2 qx = copysign(qx, transfmat[2][1] - transfmat[1][2]); qy = copysign(qy, transfmat[0][2] - transfmat[2][0]) qz = copysign(qz, transfmat[1][0] - transfmat[0][1]) hmdrot = SbRotation(qx, qy, qz, qw) return hmdrot def extracttranslation(self, transfmat): hmdpos = SbVec3f(transfmat[0][3], transfmat[1][3], transfmat[2][3]) return hmdpos def draw(self): #self.vr_compositor.waitGetPoses(self.poses, openvr.k_unMaxTrackedDeviceCount, None, 0) self.vr_compositor.waitGetPoses(self.poses, None) headPose = self.poses[openvr.k_unTrackedDeviceIndex_Hmd] if not headPose.bPoseIsValid: return True headToWorld = headPose.mDeviceToAbsoluteTracking transfmat = numpy.array([ [headToWorld.m[j][i] for i in range(4)] for j in range(3) ]) hmdrot = self.extractrotation(transfmat) hmdpos = self.extracttranslation(transfmat) self.camera0.orientation.setValue(hmdrot) self.camera0.position.setValue(self.basePosition0 + hmdpos) self.camera1.orientation.setValue(hmdrot) self.camera1.position.setValue(self.basePosition1 + hmdpos) for eye in range(2): glBindFramebuffer(GL_FRAMEBUFFER, self.frame_buffers[eye]) #coin3d rendering glUseProgram(0) if eye == 0: self.m_sceneManager.setSceneGraph(self.rootScene0) if eye == 1: self.m_sceneManager.setSceneGraph(self.rootScene1) glEnable(GL_CULL_FACE) glEnable(GL_DEPTH_TEST) self.m_sceneManager.render() glDisable(GL_CULL_FACE) glDisable(GL_DEPTH_TEST) glClearDepth(1.0) #end coin3d rendering self.vr_compositor.submit(self.eyes[eye], self.textures[eye]) return True def run(self): self.vr_system = openvr.init(openvr.VRApplication_Scene) self.vr_compositor = openvr.VRCompositor() poses_t = openvr.TrackedDevicePose_t * openvr.k_unMaxTrackedDeviceCount self.poses = poses_t() self.w, self.h = self.vr_system.getRecommendedRenderTargetSize() SDL_Init(SDL_INIT_VIDEO) self.window = SDL_CreateWindow (b"test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 100, 100, SDL_WINDOW_SHOWN|SDL_WINDOW_OPENGL) self.context = SDL_GL_CreateContext(self.window) SDL_GL_MakeCurrent(self.window, self.context) self.depth_buffer = glGenRenderbuffers(1) self.frame_buffers = glGenFramebuffers(2) self.texture_ids = glGenTextures(2) self.textures = [None] * 2 self.eyes = [openvr.Eye_Left, openvr.Eye_Right] self.camToHead = [None] * 2 self.proj_raw = [None] * 2 self.nearZ = 0.01 self.farZ = 500 for eye in range(2): glBindFramebuffer(GL_FRAMEBUFFER, self.frame_buffers[eye]) glBindRenderbuffer(GL_RENDERBUFFER, self.depth_buffer) glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, self.w, self.h) glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, self.depth_buffer) glBindTexture(GL_TEXTURE_2D, self.texture_ids[eye]) glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, self.w, self.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, None) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self.texture_ids[eye], 0) texture = openvr.Texture_t() texture.handle = int(self.texture_ids[eye]) texture.eType = openvr.TextureType_OpenGL texture.eColorSpace = openvr.ColorSpace_Gamma self.textures[eye] = texture self.proj_raw[eye]= self.vr_system.getProjectionRaw(self.eyes[eye]) #void GetProjectionRaw( Hmd_Eye eEye, float *pfLeft, float *pfRight, float *pfTop, float *pfBottom ) eyehead = self.vr_system.getEyeToHeadTransform(self.eyes[eye]) #[0][3] is eye-center distance self.camToHead[eye] = numpy.array([ [eyehead.m[j][i] for i in range(4)] for j in range(3) ]) self.setupcameras() self.setupscene() while self._running: self.draw() def terminate(self): self._running = False glDeleteBuffers(1, [self.depth_buffer]) for eye in range(2): glDeleteBuffers(1, [self.frame_buffers[eye]]) self.rootScene0.unref() self.rootScene1.unref() SDL_GL_DeleteContext(self.context) SDL_DestroyWindow(self.window) SDL_Quit() openvr.shutdown()
def main(): width = 1600 height = 1200 timelimit = 10 modeltranslation = 200 SDL_Init(SDL_INIT_VIDEO) window = SDL_CreateWindow(b"benchmark", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL) context = SDL_GL_CreateContext(window) SDL_GL_SetSwapInterval(0) #no v-sync #coin3d setup vpRegion = SbViewportRegion( width, height, ) m_sceneManager = SoSceneManager() m_sceneManager.setViewportRegion(vpRegion) m_sceneManager.setBackgroundColor(SbColor(0.0, 0.0, 0.8)) rootScene = SoSeparator() rootScene.ref() camera = SoFrustumCamera() basePosition = SbVec3f(0.0, 0.0, 0.0) camera.position.setValue(basePosition) camera.focalDistance.setValue(5.0) camera.viewportMapping.setValue(SoCamera.LEAVE_ALONE) camera.nearDistance.setValue(0.1) camera.farDistance.setValue(10000.0) rootScene.addChild(camera) light = SoDirectionalLight() light2 = SoDirectionalLight() rootScene.addChild(light) rootScene.addChild(light2) trans = SoTranslation() trans.translation.setValue([0, 0, -modeltranslation]) rotat = SoRotation() rotat.rotation.setValue(coin.SbVec3f(0, 1, 0), 0) rootScene.addChild( trans) #translation have to be earlier than translated object rootScene.addChild(rotat) sg = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph() rootScene.addChild(sg) #get active scenegraph m_sceneManager.setSceneGraph(rootScene) notfinished = 1 angle = 0 frames = 0 start = time() # Loop until time limit happens while notfinished: glUseProgram(0) #coin3d rendering angle = angle + 0.001 frames = frames + 1 rotat.rotation.setValue(coin.SbVec3f(0, 1, 0), angle) glEnable(GL_CULL_FACE) glEnable(GL_DEPTH_TEST) m_sceneManager.render() glDisable(GL_CULL_FACE) glDisable(GL_DEPTH_TEST) glClearDepth(1.0) # Swap front and back buffers SDL_GL_SwapWindow(window) stop = time() elapsed = stop - start if elapsed > timelimit: notfinished = 0 print(frames, ' in ', elapsed, 'seconds, ', (frames / elapsed), 'fps') rootScene.unref() SDL_GL_DeleteContext(context) SDL_DestroyWindow(window) SDL_Quit()
class Chapter(QtCore.QObject): """A Chapter""" pageChanged = QtCore.pyqtSignal(Page, int) def __init__(self, name=""): super(Chapter, self).__init__() self.name = name self.book = None self.root = SoSeparator() self.root.setName("Chapter:root") self.pagesSwitch = SoSwitch() self.pagesSwitch.setName("Chapter:pages") self.root.addChild(self.pagesSwitch) self.__pages = nodeDict() ## ============================ self.setupGui() def setupGui(self): ## self.widget has next, prev buttons, plus a QStackedWidget for holding per page controls self.widget = ChangePageUI() ## the initial state self.widget.previous.hide() self.widget.next.hide() connect(self.widget.next, "clicked(bool)", self.nextPage) connect(self.widget.previous, "clicked(bool)", self.prevPage) ## ============================ self.notesStack = QtGui.QStackedWidget() ## ============================ def setBook(self, book): self.book = book @property def pages(self): """The list of pages""" return self.__pages def createPage(self): """ Creates a new page and appends it to this chapter """ page = Page() self.addPage(page) return page def addPage(self, page): """ Adds 'page' to this chapter. page can be a Page or a SoNode. Searches page for a 'getGui' function, which should return a widget. @param page: Page | SoNode """ ## ============================ ## page can be a Page or SoNode root = getattr(page, "root", page) self.pages[root] = page self.pagesSwitch.addChild(root) ## ============================ guiLayout = QtGui.QVBoxLayout() guiLayout.setMargin(0) guiLayout.setSpacing(0) widget = QtGui.QWidget() widget.setObjectName("PageGui") widget.setLayout(guiLayout) self.widget.pageStack.addWidget(widget) ## ============================ notesLayout = QtGui.QVBoxLayout() notesLayout.setMargin(0) notesLayout.setSpacing(0) widget = QtGui.QWidget() widget.setObjectName("PageNotas") widget.setLayout(notesLayout) self.notesStack.addWidget(widget) ## ============================ ## this sets self.pagesSwitch, self.widget.pageStack, self.notasStack ## only change the page if theres a book already if self.book is not None: self.whichPage = len(self.pagesSwitch) - 1 ## ============================ guiLayout.addWidget(page.getGui()) notesLayout.addWidget(page.getNotes()) ## ============================ if len(self.pagesSwitch) == 2: self.widget.previous.show() self.widget.next.show() def getGui(self): return self.widget def getNotes(self): return self.notesStack def chapterSpecificIn(self): """code to be executed whenever the chapter is displayed this is intended for global changes to the scenegraph that are needed by this chapter """ pass @property def page(self): """the current page""" if self.whichPage < 0: return None return self.pages[self.pagesSwitch[self.whichPage]] def getWhichPage(self): """ Returns the index of the current page """ return self.pagesSwitch.whichChild.getValue() def setWhichPage(self, n): """ Activates the n-th page @param n: """ if len(self.pagesSwitch) > 0: self.pagesSwitch.getChild(n) self.pagesSwitch.whichChild = n self.widget.pageStack.setCurrentIndex(n) self.notesStack.setCurrentIndex(n) self.pageChanged.emit(self.page, n) whichPage = property(getWhichPage, setWhichPage) def changePage(self, direction): self.whichPage = (self.whichPage + direction) % len(self.pagesSwitch) def nextPage(self): self.changePage(1) def prevPage(self): self.changePage(-1)
class BaseObject(object): """Common functionality for all graphic objects. It's just a wrapper around a SoSeparator It has this OI structure: Switch { Separator { DrawStyle {} Translation { translation 0 0 0 } } } Has methods for hide/show itself, and for translation """ def __init__(self): self.animation = None self.root = SoSwitch() self.separator = SoSeparator() self.drawStyle = SoDrawStyle() self.translation = SoTranslation() self.root.addChild(self.separator) self.separator.addChild(self.drawStyle) self.separator.addChild(self.translation) self.translation.translation = (0, 0, 0) self.show() @fluid def setVisible(self, visible): self.root.whichChild = SO_SWITCH_ALL if visible else SO_SWITCH_NONE def getVisible(self): return self.root.whichChild.getValue() == SO_SWITCH_ALL visible = property(fget=getVisible, fset=setVisible) @fluid def show(self): self.setVisible(True) @fluid def hide(self): self.setVisible(False) @fluid def setName(self,name): self.root.setName(name) @fluid def setBoundingBox(self, xrange=None, yrange=None, zrange=None): """ @param xrange: 2-tuple @param yrange: 2-tuple @param zrange: 2-tuple """ def createPlane(normalref, point): sfplane = SoSFPlane() sfplane.setValue(SbPlane(normalref, point)) return sfplane if yrange is not None: self.clipPlaneXZ1 = SoClipPlane() self.clipPlaneXZ2 = SoClipPlane() self.clipPlaneXZ1.plane = createPlane(SbVec3f(0, 1, 0), SbVec3f(0, yrange[0], 0)) self.clipPlaneXZ2.plane = createPlane(SbVec3f(0, -1, 0), SbVec3f(0, yrange[1], 0)) self.separator.insertChild(self.clipPlaneXZ1, 0) self.separator.insertChild(self.clipPlaneXZ2, 1) if xrange is not None: self.clipPlaneYZ1 = SoClipPlane() self.clipPlaneYZ2 = SoClipPlane() self.clipPlaneYZ1.plane = createPlane(SbVec3f(1, 0, 0), SbVec3f(xrange[0], 0, 0)) self.clipPlaneYZ2.plane = createPlane(SbVec3f(-1, 0, 0), SbVec3f(xrange[1], 0, 0)) self.separator.insertChild(self.clipPlaneYZ1, 2) self.separator.insertChild(self.clipPlaneYZ2, 3) if zrange is not None: self.clipPlaneXY1 = SoClipPlane() self.clipPlaneXY2 = SoClipPlane() self.clipPlaneXY1.plane = createPlane(SbVec3f(0, 0, 1), SbVec3f(0, 0, zrange[0])) self.clipPlaneXY2.plane = createPlane(SbVec3f(0, 0, -1), SbVec3f(0, 0, zrange[1])) self.separator.insertChild(self.clipPlaneXY1, 4) self.separator.insertChild(self.clipPlaneXY2, 5) @fluid def setDrawStyle(self, style): self.drawStyle.style = style @fluid def setOrigin(self, pos): self.translation.translation = pos def getOrigin(self): return self.translation.translation.getValue() origin = property(fget=getOrigin, fset=setOrigin) def getAnimation(self): return self.animation def resetObjectForAnimation(self): pass def toText(self): """obtains the openinventor format representation""" wa = SoWriteAction() return wa.apply(self.root) @classmethod def Create(cls, oi_object): bo = cls() bo.separator.addChild(oi_object) return bo
if __name__ == "__main__": import sys from PyQt4 import QtGui from pivy.coin import SoSeparator, SoCone, SoSphere, SoCube app = QtGui.QApplication(sys.argv) viewer = Viewer(lights=False) ## ============================ viewer.book.createChapter() ## ============================ viewer.chapter.createPage() sep = SoSeparator() sep.getGui = lambda: QtGui.QLabel("<center><h1>Sphere+Cone</h1></center>") sphere = SoSphere() cone = SoCone() sep.addChild(sphere) sep.addChild(cone) viewer.page.addChild(sep) ## ============================ viewer.chapter.createPage() cube = SoCube() cube.getGui = lambda: QtGui.QLabel("<center><h1>Cubo</h1></center>") viewer.page.addChild(cube) ## ============================ viewer.whichPage = 0 viewer.resize(400, 400) viewer.show() viewer.chaptersStack.show() sys.exit(app.exec_())
class Page(QtCore.QObject): """The base class of a container node""" def __init__(self, name=""): QtCore.QObject.__init__(self) self.name = name self.root = SoSeparator() self.root.setName("Page:root") self.children = nodeDict() self.camera_position = None self.camera_point_at = None self.camera_viewAll = True ## ========================= self.animations = [] self.objectsForAnimate = [] self.coordPlanes = {} ## ========================= self.setupGui() self.setupAxis() self.showAxis(False) def setupGui(self): layout = QtGui.QVBoxLayout() self.widget = QtGui.QWidget() self.widget.setLayout(layout) if self.name != "": title = QtGui.QLabel("<center><h1>%s</h1></center>" % self.name) title.setWordWrap(True) layout.addWidget(title) layout.addStretch() ## ============================ notes = QtGui.QLabel(self.__doc__) notes.setWordWrap(True) notes.setTextFormat(QtCore.Qt.RichText) sa = QtGui.QScrollArea() sa.setWidget(notes) sa.setWidgetResizable(True) sa.setHorizontalScrollBarPolicy(1) sa.setFrameStyle(QtGui.QFrame.Plain) notes_layout = QtGui.QVBoxLayout() notes_layout.addWidget(sa) notes_layout.addStretch() self.notesWidget = QtGui.QWidget() self.notesWidget.setLayout(notes_layout) def getGui(self): return self.widget def getNotes(self): return self.notesWidget def addWidget(self, widget): self.widget.layout().addWidget(widget) def addLayout(self, layout): self.widget.layout().addLayout(layout) def addChild(self, node): # if `node` has an attribute root, we assume it is the OpenInventor root object # otherwise node is assumed to be an OI object root = getattr(node, "root", node) self.root.addChild(root) self.children[root] = node if hasattr(node, "getGui"): self.addWidget(node.getGui()) if hasattr(node, "updateAll"): node.updateAll() def addChildren(self, lst): for c in lst: self.addChild(c) def addWidgetChild(self, arg): widget, node = arg self.addWidget(widget) self.addChild(node) def getChildren(self): return self.children.values() def setupPlanes(self, r0=(-1, 1, 5)): self.coordPlanes = { 'xy': BasePlane(plane="xy").setDiffuseColor((1, 1, 0)), 'xz': BasePlane(plane="xz").setDiffuseColor((1, 0, 1)), 'yz': BasePlane(plane="yz").setDiffuseColor((0, 1, 1)) } for p in self.coordPlanes.values(): p.setRange(r0) p.setHeight(r0[0]) self.addChild(p) def showAxis(self, show): """ @param show: bool """ self.axis_x.setVisible(show) self.axis_y.setVisible(show) self.axis_z.setVisible(show) def setupAxis(self): self.axis_x = Arrow(Vec3(-5, 0, 0), Vec3(5, 0, 0)) self.axis_y = Arrow(Vec3(0, -5, 0), Vec3(0, 5, 0)) self.axis_z = Arrow(Vec3(0, 0, -5), Vec3(0, 0, 5)) self.axis_x.setDiffuseColor((1, 0, 0)).setWidthFactor(.2) self.axis_y.setDiffuseColor((0, 1, 0)).setWidthFactor(.2) self.axis_z.setDiffuseColor((0, 0, 1)).setWidthFactor(.2) self.addChildren([self.axis_x, self.axis_y, self.axis_z]) def setupAnimations(self, objects): """ Extracts the 'animation' property of the objects and chains them """ self.objectsForAnimate = objects self.animations = [getattr(ob, 'animation', ob) for ob in objects] Animation.chain(self.animations, pause=1000) Button("inicio", self.animate, parent=self) def animate(self): for ob in self.objectsForAnimate: ob.resetObjectForAnimation() self.animations[0].start()
class BaseObject(object): """Common functionality for all graphic objects. It's just a wrapper around a SoSeparator It has this OI structure: Switch { Separator { DrawStyle {} Translation { translation 0 0 0 } } } Has methods for hide/show itself, and for translation """ def __init__(self): self.animation = None self.root = SoSwitch() self.separator = SoSeparator() self.drawStyle = SoDrawStyle() self.translation = SoTranslation() self.root.addChild(self.separator) self.separator.addChild(self.drawStyle) self.separator.addChild(self.translation) self.translation.translation = (0, 0, 0) self.show() @fluid def setVisible(self, visible): self.root.whichChild = SO_SWITCH_ALL if visible else SO_SWITCH_NONE def getVisible(self): return self.root.whichChild.getValue() == SO_SWITCH_ALL visible = property(fget=getVisible, fset=setVisible) @fluid def show(self): self.setVisible(True) @fluid def hide(self): self.setVisible(False) @fluid def setName(self, name): self.root.setName(name) @fluid def setBoundingBox(self, xrange=None, yrange=None, zrange=None): """ @param xrange: 2-tuple @param yrange: 2-tuple @param zrange: 2-tuple """ def createPlane(normalref, point): sfplane = SoSFPlane() sfplane.setValue(SbPlane(normalref, point)) return sfplane if yrange is not None: self.clipPlaneXZ1 = SoClipPlane() self.clipPlaneXZ2 = SoClipPlane() self.clipPlaneXZ1.plane = createPlane(SbVec3f(0, 1, 0), SbVec3f(0, yrange[0], 0)) self.clipPlaneXZ2.plane = createPlane(SbVec3f(0, -1, 0), SbVec3f(0, yrange[1], 0)) self.separator.insertChild(self.clipPlaneXZ1, 0) self.separator.insertChild(self.clipPlaneXZ2, 1) if xrange is not None: self.clipPlaneYZ1 = SoClipPlane() self.clipPlaneYZ2 = SoClipPlane() self.clipPlaneYZ1.plane = createPlane(SbVec3f(1, 0, 0), SbVec3f(xrange[0], 0, 0)) self.clipPlaneYZ2.plane = createPlane(SbVec3f(-1, 0, 0), SbVec3f(xrange[1], 0, 0)) self.separator.insertChild(self.clipPlaneYZ1, 2) self.separator.insertChild(self.clipPlaneYZ2, 3) if zrange is not None: self.clipPlaneXY1 = SoClipPlane() self.clipPlaneXY2 = SoClipPlane() self.clipPlaneXY1.plane = createPlane(SbVec3f(0, 0, 1), SbVec3f(0, 0, zrange[0])) self.clipPlaneXY2.plane = createPlane(SbVec3f(0, 0, -1), SbVec3f(0, 0, zrange[1])) self.separator.insertChild(self.clipPlaneXY1, 4) self.separator.insertChild(self.clipPlaneXY2, 5) @fluid def setDrawStyle(self, style): self.drawStyle.style = style @fluid def setOrigin(self, pos): self.translation.translation = pos def getOrigin(self): return self.translation.translation.getValue() origin = property(fget=getOrigin, fset=setOrigin) def getAnimation(self): return self.animation def resetObjectForAnimation(self): pass def toText(self): """obtains the openinventor format representation""" wa = SoWriteAction() return wa.apply(self.root) @classmethod def Create(cls, oi_object): bo = cls() bo.separator.addChild(oi_object) return bo
from PyQt4 import QtGui from pivy.coin import SoSeparator, SoCone, SoSphere, SoCube # from pivy.gui.soqt import SoQt # SoQt.init(None) app = QtGui.QApplication(sys.argv) viewer = Viewer(lights=False) ## ============================ viewer.book.createChapter() ## ============================ viewer.chapter.createPage() sep = SoSeparator() sep.getGui = lambda: QtGui.QLabel("<center><h1>Sphere+Cone</h1></center>") sphere = SoSphere() cone = SoCone() sep.addChild(sphere) sep.addChild(cone) viewer.page.addChild(sep) ## ============================ viewer.chapter.createPage() cube = SoCube() cube.getGui = lambda: QtGui.QLabel("<center><h1>Cubo</h1></center>") viewer.page.addChild(cube) ## ============================ viewer.whichPage = 0 viewer.resize(400, 400) viewer.show() viewer.chaptersStack.show() sys.exit(app.exec_())
class Page(QtCore.QObject): """The base class of a container node""" def __init__(self, name=""): QtCore.QObject.__init__(self) self.name = name self.root = SoSeparator() self.root.setName("Page:root") self.children = nodeDict() self.camera_position = None self.camera_point_at = None self.camera_viewAll = True ## ========================= self.animations = [] self.objectsForAnimate = [] self.coordPlanes = {} ## ========================= self.setupGui() self.setupAxis() self.showAxis(False) def setupGui(self): layout = QtGui.QVBoxLayout() self.widget = QtGui.QWidget() self.widget.setLayout(layout) if self.name != "": title = QtGui.QLabel("<center><h1>%s</h1></center>" % self.name) title.setWordWrap(True) layout.addWidget(title) layout.addStretch() ## ============================ notes = QtGui.QLabel(self.__doc__) notes.setWordWrap(True) notes.setTextFormat(QtCore.Qt.RichText) sa = QtGui.QScrollArea() sa.setWidget(notes) sa.setWidgetResizable(True) sa.setHorizontalScrollBarPolicy(1) sa.setFrameStyle(QtGui.QFrame.Plain) notes_layout = QtGui.QVBoxLayout() notes_layout.addWidget(sa) notes_layout.addStretch() self.notesWidget = QtGui.QWidget() self.notesWidget.setLayout(notes_layout) def getGui(self): return self.widget def getNotes(self): return self.notesWidget def addWidget(self, widget): self.widget.layout().addWidget(widget) def addLayout(self, layout): self.widget.layout().addLayout(layout) def addChild(self, node): # if `node` has an attribute root, we assume it is the OpenInventor root object # otherwise node is assumed to be an OI object root = getattr(node, "root", node) self.root.addChild(root) self.children[root] = node if hasattr(node, "getGui"): self.addWidget(node.getGui()) if hasattr(node, "updateAll"): node.updateAll() def addChildren(self, lst): for c in lst: self.addChild(c) def addWidgetChild(self, arg): widget, node = arg self.addWidget(widget) self.addChild(node) def getChildren(self): return self.children.values() def setupPlanes(self, r0=(-1, 1, 5)): self.coordPlanes = { 'xy': BasePlane(plane="xy").setDiffuseColor((1, 1, 0)), 'xz': BasePlane(plane="xz").setDiffuseColor((1, 0, 1)), 'yz': BasePlane(plane="yz").setDiffuseColor((0, 1, 1)) } for p in self.coordPlanes.values(): p.setRange(r0) p.setHeight(r0[0]) self.addChild(p) def showAxis(self, show): """ @param show: bool """ self.axis_x.setVisible(show) self.axis_y.setVisible(show) self.axis_z.setVisible(show) def setupAxis(self): self.axis_x = Arrow(Vec3(-5, 0, 0), Vec3(5, 0, 0)) self.axis_y = Arrow(Vec3(0, -5, 0), Vec3(0, 5, 0)) self.axis_z = Arrow(Vec3(0, 0, -5), Vec3(0, 0, 5)) self.axis_x.setDiffuseColor((1, 0, 0)).setWidthFactor(.2) self.axis_y.setDiffuseColor((0, 1, 0)).setWidthFactor(.2) self.axis_z.setDiffuseColor((0, 0, 1)).setWidthFactor(.2) self.addChildren([self.axis_x, self.axis_y, self.axis_z ]) def setupAnimations(self, objects): """ Extracts the 'animation' property of the objects and chains them """ self.objectsForAnimate = objects self.animations = [ getattr(ob, 'animation', ob) for ob in objects ] Animation.chain(self.animations, pause=1000) Button("inicio", self.animate, parent=self) def animate(self): for ob in self.objectsForAnimate: ob.resetObjectForAnimation() self.animations[0].start()
class ViewProviderLine: def __init__(self, obj): "Add our custom features to this view provider" obj.addProperty("App::PropertyColor","StartPointColor","Line","Start point color").StartPointColor=(0.0,0.0,0.0) obj.addProperty("App::PropertyColor","EndPointColor","Line","End point color").EndPointColor=(0.0,0.0,0.0) obj.LineColor = (0.0,0.0,0.0) #existing Part::FeaturePython property obj.PointSize = 4 #existing Part::FeaturePython property obj.LineWidth = 2 #existing Part::FeaturePython property obj.Selectable = True #existing Part::FeaturePython property obj.Proxy = self #some kind of FreeCAD internal here, this view provider object is set as the FreeCAD view object proxy. # I guess if a proxy exists, it's used instead of the standard one. def attach(self, obj): "Setup the scene sub-graph of the view provider" #create group for display mode and add line, start point and end point nodes self.group = SoSeparator() self.lineNode = SoSeparator() self.startPointNode = SoSeparator() self.endPointNode = SoSeparator() self.group.addChild(self.lineNode) self.group.addChild(self.startPointNode) self.group.addChild(self.endPointNode) #add line colour self.lineColor = SoBaseColor() self.lineNode.addChild(self.lineColor) #add draw style self.drawStyle = SoDrawStyle() self.lineNode.addChild(self.drawStyle) self.startPointNode.addChild(self.drawStyle) self.endPointNode.addChild(self.drawStyle) #add start point color self.startPointColor = SoBaseColor() self.startPointNode.addChild(self.startPointColor) #add end point colour self.endPointColor = SoBaseColor() self.endPointNode.addChild(self.endPointColor) #add coordinate node self.coords = SoCoordinate3() self.lineNode.addChild(self.coords) self.endPointNode.addChild(self.coords) self.startPointNode.addChild(self.coords) #add edge (using PartGui::SoBrepEdgeSet, has selectability built in) #self.lineSet = SoLineSet() self.lineSet = SoType.fromName("SoBrepEdgeSet").createInstance() self.lineSet.coordIndex.setValues(0,2,(0,1)) self.lineNode.addChild(self.lineSet) #add start point (using PartGui::SoBrepPointSet, has selectability built in) #self.startPoint = SoPointSet() self.startPoint = SoType.fromName("SoBrepPointSet").createInstance() self.startPoint.startIndex = 0 self.startPoint.numPoints = 1 self.startPointNode.addChild(self.startPoint) #add end point (using PartGui::SoBrepPointSet, has selectability built in) #self.endPoint = SoPointSet() self.endPoint = SoType.fromName("SoBrepPointSet").createInstance() self.endPoint.startIndex = 1 self.endPoint.numPoints = 1 self.endPointNode.addChild(self.endPoint) #assign properties to nodes self.onChanged(obj,"LineColor") self.onChanged(obj,"StartPointColor") self.onChanged(obj,"EndPointColor") self.onChanged(obj,"PointSize") self.onChanged(obj,"LineWidth") #add display mode to view object obj.addDisplayMode(self.group,"Default"); def updateData(self, fp, prop): "If a property of the handled feature has changed we have the chance to handle this here" # fp is the handled feature, prop is the name of the property that has changed if prop == "StartPoint": s = fp.getPropertyByName("StartPoint") self.coords.point.set1Value(0,s[0],s[1],s[2]) elif prop == "EndPoint": s = fp.getPropertyByName("EndPoint") self.coords.point.set1Value(1,s[0],s[1],s[2]) def getDisplayModes(self,obj): "Return a list of display modes." modes=[] modes.append("Default") return modes def getDefaultDisplayMode(self): "Return the name of the default display mode. It must be defined in getDisplayModes." return "Default" def setDisplayMode(self,mode): return mode def onChanged(self, vp, prop): "Here we can do something when a single property got changed" if prop == "LineColor": c = vp.getPropertyByName("LineColor") self.lineColor.rgb.setValue(c[0],c[1],c[2]) elif prop == "StartPointColor": c = vp.getPropertyByName("StartPointColor") self.startPointColor.rgb.setValue(c[0],c[1],c[2]) elif prop == "EndPointColor": c = vp.getPropertyByName("EndPointColor") self.endPointColor.rgb.setValue(c[0],c[1],c[2]) elif prop == "PointSize": c = vp.getPropertyByName("PointSize") self.drawStyle.pointSize = c elif prop == "LineWidth": c = vp.getPropertyByName("LineWidth") self.drawStyle.lineWidth = c def getIcon(self): return """ /* XPM */ static const char * ViewProviderBox_xpm[] = { "16 16 3 1", " c #FFFFFF", ". c #3F48CC", "+ c #00A2E8", " ", " ... ", " ..... ", " ..+.. ", " +..... ", " +++... ", " +++++ ", " +++++ ", " +++++ ", " +++++ ", " ...++++ ", ".....++ ", "..+..+ ", "..... ", " ... ", " "}; """ def __getstate__(self): return None def __setstate__(self,state): return None
class edge(object): "edge creation base class" def Activated(self, obj = None, sp=None): #initalise some variables self.obj = obj self.doc = FreeCAD.ActiveDocument self.view = FreeCADGui.ActiveDocument.ActiveView self.currentPoint = None #will be type FreeCAD.Vector self.lockLine = False #will be type FreeCAD.Vector self.snapPoints = functions.getSnapPoints() #get list of snap points and lines in current view self.snapLines = functions.getSnapLines() if sp: #if a start point is predefined then jump into the appropriate state. self.sp = sp self.snapLines=self.spSnapEntry(self.sp, self.snapLines) #add start point snap lines self.state = 2 else: self.state=0 functions.edgeSelection(False) #turn off selection of existing edge objects self.call = self.view.addEventCallbackPivy(SoEvent.getClassTypeId(),self.event) #create callback for any event self.sceneGraph = self.view.getSceneGraph() #temp geometry inialize for drawing temporary geometry self.tempNode = SoSeparator() #top node for all temp geometry #line node self.tempLine = SoSeparator() self.lineCoords = SoCoordinate3() self.lineSet = SoLineSet() self.lineColor = SoBaseColor() self.lineColor.rgb = (0,0,0) self.tempLine.addChild(self.lineCoords) self.tempLine.addChild(self.lineColor) self.tempLine.addChild(self.lineSet) #point highlight node self.tempPoint = SoSeparator() self.pointCoords = SoCoordinate3() self.pointSet = SoPointSet() self.pointColor = SoBaseColor() self.drawStyle = SoDrawStyle() self.pointColor.rgb = (1,1,1) self.drawStyle.style.setValue("INVISIBLE") self.drawStyle.pointSize = 5 self.tempPoint.addChild(self.pointCoords) self.tempPoint.addChild(self.pointColor) self.tempPoint.addChild(self.drawStyle) self.tempPoint.addChild(self.pointSet) #snap line node self.snapLine = SoSeparator() self.snapLineCoords = SoCoordinate3() self.snapLineSet = SoLineSet() self.snapLineColor = SoBaseColor() self.snapLineDrawStyle = SoDrawStyle() self.snapLineColor.rgb = (1,1,1) self.snapLineDrawStyle.style.setValue("INVISIBLE") self.snapLine.addChild(self.snapLineCoords) self.snapLine.addChild(self.snapLineColor) self.snapLine.addChild(self.snapLineDrawStyle) self.snapLine.addChild(self.snapLineSet) #add temp geometry nodes to scene graph self.tempNode.addChild(self.tempPoint) self.tempNode.addChild(self.snapLine) self.tempNode.addChild(self.tempLine) self.sceneGraph.addChild(self.tempNode) def event(self,eventCB): "Checks event type, passes on to appropriate function" event = eventCB.getEvent() type = event.getTypeId() leftButton = 1 rollerButton = 3 down = 1 up = 0 if type == SoLocation2Event.getClassTypeId(): self.mouseMove(event) elif type == SoMouseButtonEvent.getClassTypeId() and event.getButton() == leftButton: if event.getState() == down: self.mouseButtonDown() elif event.getState() == up: self.mouseButtonUp() elif type == SoKeyboardEvent.getClassTypeId(): self.keyboard(event) else: FreeCAD.Console.PrintMessage("Some other event just happened\n") def mouseMove(self,event): pos = event.getPosition() #get mouse position from event (in xy pixel coordinates) linePoint, lineSnapped, snapLine1, snapLine2, self.cursorDir = functions.snapLine(self.view, pos, self.snapLines, 10,self.lockLine) #check if in range of snap line(s) if self.state ==4: #get the snap point, depending on state pointSnapped = False #at state 4 there is no snap points (state 4 is for picking center point of an arc) else: pointPoint, pointSnapped = functions.snapPoint(self.view, pos, self.snapPoints, 10) #check if in range of snap point #next draw the snap lines or points and assign the current point if pointSnapped: self.snapLineDrawStyle.style.setValue("INVISIBLE") # turns off the visualisation of any previous snap lines self.pointCoords.point.set1Value(0,pointPoint[0],pointPoint[1],pointPoint[2]) #puts the snap cooridinates into the scene graph self.drawStyle.style.setValue("POINTS") #turns on the visualisation of the snap point self.currentPoint = pointPoint #sets the current point to the snap point such that if the mouse is clicked the snap point is used elif lineSnapped: #line snap only if no point snap, so point snap had priority self.snapLineSet.numVertices.setValue(2)#two vertices for a line from snap point to base point self.pointCoords.point.set1Value(0,linePoint[0],linePoint[1],linePoint[2])#adds line snap point to scene graph self.drawStyle.style.setValue("POINTS") #turns on visualiation of point basePoint = snapLine1[0] # get first vertex of snap line from the snap line base point self.snapLineCoords.point.set1Value(0,basePoint[0],basePoint[1],basePoint[2]) #put the line coordinates into the scene graph self.snapLineCoords.point.set1Value(1,linePoint[0],linePoint[1],linePoint[2]) if snapLine2: #if there is a second snap line basePoint2 = snapLine2[0] # get last point from base point of second line(line is drawn from base point to snap point to base point) self.snapLineCoords.point.set1Value(2,basePoint2[0],basePoint2[1],basePoint2[2]) #put the line coordinates into the scene graph self.snapLineSet.numVertices.setValue(3) #tell line set there are 3 vertexes to be drawn self.snapLineDrawStyle.style.setValue("LINES") #turns on visualisation of lines self.currentPoint = linePoint #sets current point to line snap point else: #if no snap is found, don't draw to screen and find cursor point self.drawStyle.style.setValue("INVISIBLE") #turn of visualisation of snap point self.snapLineDrawStyle.style.setValue("INVISIBLE") #turn of visualisation of snap line self.currentPoint = self.view.getPoint(pos[0],pos[1]) #get cursor point for current point def mouseButtonDown(self): if self.state == 0: self.sp = self.currentPoint #record first point self.snapLines=self.spSnapEntry(self.sp, self.snapLines) #add first point to snaplines self.state = 1 #update to new state def mouseButtonUp(self): if self.state == 1: self.state = 2 def spSnapEntry(self,sp,snapLines): "this block adds the first coordinate selected to the snap line list so the line will snap to the orthogonal projections of it" entry= [sp,FreeCAD.Vector(1,0,0),None] #horizontal snap direction entry2 = [sp,FreeCAD.Vector(0,1,0),None] #vertical snap direction entry3 = [sp,FreeCAD.Vector(1,1,0),None] #45 snap direction entry4 = [sp,FreeCAD.Vector(1,-1,0),None] #-45 snap direction snapLines.append(entry) snapLines.append(entry2) snapLines.append(entry3) snapLines.append(entry4) return snapLines def keyboard(self,event): pass #don't currently use any key functionality def cleanUp(self): self.view.removeEventCallbackPivy(SoEvent.getClassTypeId(),self.call) #remove event callback #remove the temporary geormety by sending the removal function throught to a delay function (of the Draft Module) #This must be done as the callback traversal is still occuring and will crash if the scene grapth objects are removed underneith it nodeRef = self.sceneGraph.findChild(self.tempNode) #First we get the index ofour temp geometry node under the scene graph node #(I don't like this, can we use a use a name instead that can't be confused with another node?) f = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph().removeChild #this is the function that removes a node node from the scene grapth todo.delay(f, nodeRef) #pass the index and the function onto the delay method functions.edgeSelection(True) #turn back on selection of existing edge objects
class Book(QtCore.QObject): """A Book-like object""" chapterChanged = QtCore.pyqtSignal(int) pageChanged = QtCore.pyqtSignal(Page, int) def __init__(self): super(Book, self).__init__() self.root = SoSeparator() self.root.setName("Book:root") self.chapters = SoSwitch() self.chapters.setName("Book:chapters") self.root.addChild(self.chapters) ## this dictionary contains the chapters python objects ## not only the SoSeparator self.chaptersObjects = nodeDict() self.setupGui() def __len__(self): """The number of chapters""" return len(self.chapters) def setupGui(self): ## chapterStack has one widget (of controls) per chapter self.chaptersStack = QtGui.QStackedWidget() self.notesStack = QtGui.QStackedWidget() def createChapter(self): """Creates a new empty Chapter""" chapter = Chapter() self.addChapter(chapter) return chapter def addChapter(self, chapter): """ Appends chapter to this book @param chapter: Chapter """ ## we probably should check that chapter is derived ## from base.Chapter self.chaptersObjects[chapter.pagesSwitch] = chapter self.chapters.addChild(chapter.root) chapter.setBook(self) ## ============================ ## setup the UI self.chaptersStack.addWidget(chapter.getGui()) self.notesStack.addWidget(chapter.getNotes()) self.whichChapter = len(self.chapters) - 1 #======================================================================= chapter.pageChanged.connect(self.relayPageChangedSignal) def relayPageChangedSignal(self, page, n): logger.debug('relayPageChangedSignal: %s', n) self.pageChanged.emit(page, n) @property def chapterSwitch(self): """the switch of the current chapter""" if self.whichChapter < 0: return None return self.chapters[self.whichChapter][0] @property def chapter(self): """returns the current chapter""" if self.whichChapter < 0: return None return self.chaptersObjects[self.chapterSwitch] @property def page(self): """returns the current page in the chapter""" return self.chapter.page if self.whichChapter >= 0 else None def getWhichChapter(self): """returns the selected chapter""" return self.chapters.whichChild.getValue() def setWhichChapter(self, n): """ Sets the current chapter @param n: int """ self.chapters.whichChild = n self.chaptersStack.setCurrentIndex(n) self.notesStack.setCurrentIndex(n) self.chapter.chapterSpecificIn() self.chapterChanged.emit(n) # noinspection PyStatementEffect self.chapter.page and self.pageChanged.emit(self.chapter.page, self.chapter.whichPage) whichChapter = property(getWhichChapter, setWhichChapter)