|
|
|
Return to Code Snippets
by zzarko » Thu Jan 22, 2009 11:49 am
Here is some code I was working on past few days. It should be a visualisation of numerical calculations (i.e. bridge stability) (curently, there is some repeated random data). I followed the Panda manual about generating objects programaticaly, and used dinoint's code to embed Panda window into PyQt. Because of some problem with initialisation (commented self.ResetPos() call), you must press zero after starting to set the scene in default position (I know I colud do it with a timer, but don't like that solution). After that, you can manipulate graph with +,-,*,/,5,zero and enter. Quit with escape. Any comments and/or improvements are welcome.
- Code: Select all
# -*- coding: UTF-8 -*-
#fullscreen from pandac.PandaModules import loadPrcFileData #loadPrcFileData("", "fullscreen 1") loadPrcFileData("", "window-title Bridge") loadPrcFileData("", "window-type none")
import direct.directbase.DirectStart #from direct.showbase.DirectObject import DirectObject from pandac.PandaModules import WindowProperties
from PyQt4.QtCore import * from PyQt4.QtGui import *
P3D_WIN_WIDTH = 800 P3D_WIN_HEIGHT = 500
import direct.directbase.DirectStart from direct.showbase.DirectObject import * from pandac.PandaModules import * from direct.interval.IntervalGlobal import *
from direct.task import Task from direct.interval.IntervalGlobal import * from math import * import random import codecs import sys
#---------------------------------------------------------------------- # definitions for dynamic object creation #----------------------------------------------------------------------
graphVertexFormat = GeomVertexFormat.getV3n3c4t2()
#put here any font you like labelFont = loader.loadFont('arial.ttf') labelFont.setPointSize(10)
#---------------------------------------------------------------------- # PyQt GUI (taken from dinoint's 'post) #----------------------------------------------------------------------
class QTTest(QDialog): def __init__(self, pandaCallback, parent=None): super(QDialog, self).__init__(parent) self.setWindowTitle("Test") self.setGeometry(30,30,800,600) self.pandaContainer = QWidget(self) self.pandaContainer.setGeometry(0,0,P3D_WIN_WIDTH,P3D_WIN_HEIGHT)
self.lineedit = QLineEdit("Proba ugnjezdenog prikaza...") layout = QVBoxLayout() layout.addWidget(self.pandaContainer) layout.addWidget(self.lineedit) self.setLayout(layout) # this basically creates an idle task timer = QTimer(self) self.connect( timer, SIGNAL("timeout()"), pandaCallback ) timer.start(0)
#---------------------------------------------------------------------- # graph classes #----------------------------------------------------------------------
#3D point class GraphCoordinate3D(object): def __init__(self,cx=0,cy=0,cz=0): self.x = cx self.y = cy self.z = cz
#2D point class GraphCoordinate2D(object): def __init__(self,cx=0,cy=0): self.x = cx self.y = cy
#one subgraph class SubGraph(object): def __init__(self, gData, stripNo, parentNode, colGraph = VBase4(0,1,0,1), colAxes = VBase4(1,0,0,1), colStrip = VBase4(0,0,0,1), scale = 1, thickness = 2): self.axesPoints = [] #axes (GraphCoordinate2D) self.rotation = 0 #graph rotation (not needed?)
st = gData.strips[stripNo] #get strip data self.stri = st
#graph dimensions xmin = st.data[0].x xmax = xmin ymin = st.data[0].y ymax = ymin for i in st.data: if xmin > i.x : xmin = i.x if xmax < i.x : xmax = i.x if ymin > i.y : ymin = i.y if ymax < i.y : ymax = i.y label1Y = ymin label2Y = ymax if ymin > 0 : ymin = 0 if ymax < 0 : ymax = 1
arH = 0.2 #arrow height arW = 0.1 #arrow width yscale = 1.4 #axes scale (relative to graph size) ymax = ymax * yscale ymin = ymin * yscale #axes definition self.axesPoints.append(GraphCoordinate2D(0,0)) #[0](0,0) for Y self.axesPoints.append(GraphCoordinate2D(0,ymax)) #[1]end of Y self.axesPoints.append(GraphCoordinate2D(-arW,ymax-arH)) #[2]arrow 1 self.axesPoints.append(GraphCoordinate2D(arW,ymax-arH)) #[3]arrow 2 self.axesPoints.append(GraphCoordinate2D(0,0)) #[4](0,0) for X (so it can be different color) self.axesPoints.append(GraphCoordinate2D(xmax,0)) #[5]end of X self.axesPoints.append(GraphCoordinate2D(0,ymin)) #[6](eventually needed) more Y self.axesPoints.append(GraphCoordinate2D(xmin,0)) #[7](eventually needed) more X self.vertexData = GeomVertexData('GraphData', graphVertexFormat, Geom.UHDynamic) graphWriterVertex = GeomVertexWriter(self.vertexData, 'vertex') graphWriterNormal = GeomVertexWriter(self.vertexData, 'normal') graphWriterColor = GeomVertexWriter(self.vertexData, 'color') graphWriterTexcoord = GeomVertexWriter(self.vertexData, 'texcoord')
graphPrimitive = GeomLines(Geom.UHStatic) graphPrimitiveStrip = GeomLines(Geom.UHStatic)
#axes points firstPoint = 0 for i in self.axesPoints: graphWriterVertex.addData3f(i.x*scale,0,i.y*scale) #XYZ graphWriterNormal.addData3f(0,0,1) #XYZ if firstPoint in [4,5,7]: graphWriterColor.addData4f(colStrip) #RGBA else: graphWriterColor.addData4f(colAxes) #RGBA graphWriterTexcoord.addData2f(0,0) #UV firstPoint = firstPoint + 1 #graph points lastPoint = firstPoint for i in st.data: graphWriterVertex.addData3f(i.x*scale,0,i.y*scale) #XYZ graphWriterNormal.addData3f(0,0,1) #XYZ graphWriterColor.addData4f(colGraph) #RGBA graphWriterTexcoord.addData2f(0,0) #UV lastPoint = lastPoint + 1
#axes lines graphPrimitive.addVertices(0,1) graphPrimitive.closePrimitive() graphPrimitive.addVertices(1,2) graphPrimitive.closePrimitive() graphPrimitive.addVertices(1,3) graphPrimitive.closePrimitive() if self.axesPoints[6].x <> 0 or self.axesPoints[6].y <> 0: graphPrimitive.addVertices(0,6) graphPrimitive.closePrimitive() graphPrimitiveStrip.addVertices(4,5) graphPrimitiveStrip.closePrimitive() if self.axesPoints[7].x <> 0 or self.axesPoints[7].y <> 0: graphPrimitiveStrip.addVertices(4,7) graphPrimitiveStrip.closePrimitive() #graph lines for i in range(firstPoint,lastPoint-1): graphPrimitive.addVertices(i,i+1) graphPrimitive.closePrimitive()
#node generation graphGeom = Geom(self.vertexData) graphGeom.addPrimitive(graphPrimitive) self.node = GeomNode('GraphNode') self.node.addGeom(graphGeom) self.nodePathAll = parentNode.attachNewNode("Dummy") self.nodePathGraphLab = self.nodePathAll.attachNewNode("Dummy") self.nodePathGraph = self.nodePathGraphLab.attachNewNode(self.node) self.nodePathGraph.setRenderModeThickness(thickness) self.nodePathGraphLab.setY(-0.05) graphGeomStrip = Geom(self.vertexData) graphGeomStrip.addPrimitive(graphPrimitiveStrip) self.nodeStrip = GeomNode('GraphNode') self.nodeStrip.addGeom(graphGeomStrip) self.nodePathStrip = self.nodePathAll.attachNewNode(self.nodeStrip) self.nodePathStrip.setRenderModeThickness(thickness*2) #labels self.label1 = TextNode('label1') self.label1.setText(str(round(label1Y,2))) self.label1.setFont(labelFont) self.label1NodePath = self.nodePathGraphLab.attachNewNode(self.label1) self.label1NodePath.setTwoSided(True) self.label1NodePath.setColor(colGraph) self.label1NodePath.setPos(-0.5,0,label1Y) self.label1NodePath.setScale(0.2) self.label2 = TextNode('label2') self.label2.setText(str(round(label2Y,2))) self.label2.setFont(labelFont) self.label2NodePath = self.nodePathGraphLab.attachNewNode(self.label2) self.label2NodePath.setTwoSided(True) self.label2NodePath.setColor(colGraph) self.label2NodePath.setPos(-0.5,0,label2Y) self.label2NodePath.setScale(0.2)
#rotating and positioning of graph a = gData.lines[st.p2].x - gData.lines[st.p1].x b = gData.lines[st.p2].y - gData.lines[st.p1].y angle = degrees(-atan2(b,a)) self.nodePathAll.setR(angle) self.nodePathAll.setPos(gData.lines[st.p1].x-4,0,gData.lines[st.p1].y) #data for one strip class StripData(object): def __init__(self): self.p1 = 0 #prva linija self.p2 = 0 #druga linija self.data = [] #podaci za pod-grafik (graphCoordinate2D)
#data for all subgraphs class GraphData(object): def __init__(self): self.lines = [] #koordinate linija u preseku (GraphCoordinate2D?) self.strips = [] #podaci o trakama (StripData)
self.graphs = [] #podaci o pod-graficima (SubGraph) self.scale = 1 #faktor skaliranja za ceo grafik self.node = 0 #nodePath za ceo grafik self.nodePath = 0 #nodePath za ceo grafik
#---------------------------------------------------------------------- # main program #----------------------------------------------------------------------
class World(DirectObject): def __init__(self): base.disableMouse()
#test data self.data = GraphData() #dummy node self.data.nodePath = render.attachNewNode("Graph")
#self.fnt.setSpaceAdvance(1)
#below is some just-for-testing data generation #lines definition (strip is defined by two lines) self.data.lines.append(GraphCoordinate2D(0,0)) #0 self.data.lines.append(GraphCoordinate2D(2,0)) #1 self.data.lines.append(GraphCoordinate2D(6,0)) #2 self.data.lines.append(GraphCoordinate2D(8,0)) #3 self.data.lines.append(GraphCoordinate2D(3,-2)) #4 self.data.lines.append(GraphCoordinate2D(5,-2)) #5 #strip definition st = StripData() st.p1 = 0 st.p2 = 1 a = self.data.lines[st.p2].x - self.data.lines[st.p1].x b = self.data.lines[st.p2].y - self.data.lines[st.p1].y l = sqrt(a*a + b*b) st.data.append(GraphCoordinate2D(0.0*l,1)) st.data.append(GraphCoordinate2D(0.3*l,0.5)) st.data.append(GraphCoordinate2D(0.7*l,0.3)) st.data.append(GraphCoordinate2D(1.0*l,0.7)) self.data.strips.append(st) print len(self.data.strips), self.data.strips[0].p1, self.data.strips[0].p2
st = StripData() st.p1 = 1 st.p2 = 2 a = self.data.lines[st.p2].x - self.data.lines[st.p1].x b = self.data.lines[st.p2].y - self.data.lines[st.p1].y l = sqrt(a*a + b*b) st.data.append(GraphCoordinate2D(0.0*l,1)) st.data.append(GraphCoordinate2D(0.3*l,0.5)) st.data.append(GraphCoordinate2D(0.7*l,0.3)) st.data.append(GraphCoordinate2D(1.0*l,0.7)) self.data.strips.append(st) st = StripData() st.p1 = 2 st.p2 = 3 a = self.data.lines[st.p2].x - self.data.lines[st.p1].x b = self.data.lines[st.p2].y - self.data.lines[st.p1].y l = sqrt(a*a + b*b) st.data.append(GraphCoordinate2D(0.0*l,1)) st.data.append(GraphCoordinate2D(0.3*l,0.5)) st.data.append(GraphCoordinate2D(0.7*l,0.3)) st.data.append(GraphCoordinate2D(1.0*l,0.7)) self.data.strips.append(st) st = StripData() st.p1 = 1 st.p2 = 4 a = self.data.lines[st.p2].x - self.data.lines[st.p1].x b = self.data.lines[st.p2].y - self.data.lines[st.p1].y l = sqrt(a*a + b*b) st.data.append(GraphCoordinate2D(0.0*l,1)) st.data.append(GraphCoordinate2D(0.3*l,0.5)) st.data.append(GraphCoordinate2D(0.7*l,0.3)) st.data.append(GraphCoordinate2D(1.0*l,0.7)) self.data.strips.append(st) st = StripData() st.p1 = 4 st.p2 = 5 a = self.data.lines[st.p2].x - self.data.lines[st.p1].x b = self.data.lines[st.p2].y - self.data.lines[st.p1].y l = sqrt(a*a + b*b) st.data.append(GraphCoordinate2D(0.0*l,1)) st.data.append(GraphCoordinate2D(0.3*l,0.5)) st.data.append(GraphCoordinate2D(0.7*l,0.3)) st.data.append(GraphCoordinate2D(1.0*l,0.7)) self.data.strips.append(st) st = StripData() st.p1 = 5 st.p2 = 2 a = self.data.lines[st.p2].x - self.data.lines[st.p1].x b = self.data.lines[st.p2].y - self.data.lines[st.p1].y l = sqrt(a*a + b*b) st.data.append(GraphCoordinate2D(0.0*l,1)) st.data.append(GraphCoordinate2D(0.3*l,0.5)) st.data.append(GraphCoordinate2D(0.7*l,0.3)) st.data.append(GraphCoordinate2D(1.0*l,0.7)) self.data.strips.append(st) colors = [VBase4(0,1,0,1),VBase4(0,0,1,1),VBase4(1,1,0,1),VBase4(1,0,1,1),VBase4(0,1,1,1),VBase4(1,1,1,1)] col = 0 for i in range(len(self.data.strips)): self.data.graphs.append(SubGraph(self.data, i, self.data.nodePath, scale = self.data.scale, colGraph = colors[col], colAxes = colors[col]*0.6)) col = col + 1 #self.data.nodePath.setPos(-4,0,0)
#events self.accept('escape', sys.exit) self.accept('+', self.ZoomIn) self.accept('+-repeat', self.ZoomIn) self.accept('-', self.ZoomOut) self.accept('--repeat', self.ZoomOut) self.accept('*', self.RotateCW) self.accept('*-repeat', self.RotateCW) self.accept('/', self.RotateCCW) self.accept('/-repeat', self.RotateCCW) self.accept('enter', self.Cycle) self.accept('0', self.ResetPos) self.accept('5', self.RotateZ) self.seq = 0 #this doesn't work after embedding panda into pyqt, so it's commented #self.ResetPos() def ResetPos(self): if self.seq <> 0 and self.seq.isPlaying(): return base.disableMouse() base.camera.setPos(0,-15,0) base.camera.setHpr(0,0,0) self.cycle = -2 self.Cycle()
def ZoomIn(self): if self.seq <> 0 and self.seq.isPlaying(): return posLerp = LerpPosInterval(base.camera,0.3,VBase3(0,base.camera.getY()+1,0),blendType='easeInOut') self.seq = Sequence(posLerp) self.seq.start() def ZoomOut(self): if self.seq <> 0 and self.seq.isPlaying(): return posLerp = LerpPosInterval(base.camera,0.3,VBase3(0,base.camera.getY()-1,0),blendType='easeInOut') self.seq = Sequence(posLerp) self.seq.start() def RotateCW(self): if self.seq <> 0 and self.seq.isPlaying(): return hprLerp = LerpHprInterval(base.camera,0.6,VBase3(0,0,base.camera.getR()-45),blendType='easeInOut') self.seq = Sequence(hprLerp) self.seq.start() def RotateZ(self): if self.seq <> 0 and self.seq.isPlaying(): return hprLerp = LerpHprInterval(self.data.nodePath,2,VBase3(self.data.nodePath.getH()+360,0,0),blendType='easeInOut') self.seq = Sequence(hprLerp) self.seq.start() def RotateCCW(self): if self.seq <> 0 and self.seq.isPlaying(): return hprLerp = LerpHprInterval(base.camera,0.6,VBase3(0,0,base.camera.getR()+45),blendType='easeInOut') self.seq = Sequence(hprLerp) self.seq.start()
def Cycle(self): self.cycle = self.cycle + 1 if self.cycle == len(self.data.graphs): self.cycle = -1 cnt = 0 for i in self.data.graphs: if self.cycle == -1 or self.cycle == cnt: i.nodePathGraphLab.show() else: i.nodePathGraphLab.hide() cnt = cnt + 1 def step(self): taskMgr.step() def bindToWindow(self, windowHandle): wp = WindowProperties().getDefault() wp.setOrigin(0,0) wp.setSize(P3D_WIN_WIDTH, P3D_WIN_HEIGHT) wp.setParentWindow(windowHandle) base.openDefaultWindow(props=wp) self.wp = wp
if __name__ == '__main__': world = World()
app = QApplication(sys.argv) form = QTTest(world.step) x = int(form.winId()) world.bindToWindow(int(form.winId())) form.show() app.exec_()
#w = World()
#run()
Last edited by zzarko on Thu Jan 22, 2009 3:27 pm, edited 1 time in total.
-
zzarko
-
- Posts: 14
- Joined: Mon Jun 30, 2008 11:25 am
by rdb » Thu Jan 22, 2009 12:44 pm
Sure looks interesting. Could you maybe post it using UNIX newlines instead of windows newlines?
Also, I'm getting this error with 1.5.4:
- Code: Select all
labelFont.setPointSize(10) AttributeError: 'libpanda.StaticTextFont' object has no attribute 'setPointSize'
On 1.6.0, I have no problems, however. You might wanna consider changing this so it works with 1.5.4, too.
I rarely respond to PMs
-
rdb
-
- Posts: 8565
- Joined: Mon Dec 04, 2006 5:58 am
- Location: Netherlands
-
by drwr » Thu Jan 22, 2009 1:57 pm
Try:
- Code: Select all
labelFont = loader.loadFont('arial.ttf', pointSize = 10)
David
-
drwr
-
- Posts: 11253
- Joined: Fri Feb 13, 2004 12:42 pm
- Location: Glendale, CA
by zzarko » Thu Jan 22, 2009 3:31 pm
pro-rsoft wrote:Sure looks interesting. Could you maybe post it using UNIX newlines instead of windows newlines?
I didn't check that, sorry, it's OK now. Also, I'm getting this error with 1.5.4: - Code: Select all
labelFont.setPointSize(10) AttributeError: 'libpanda.StaticTextFont' object has no attribute 'setPointSize'
On 1.6.0, I have no problems, however. You might wanna consider changing this so it works with 1.5.4, too.
I was doing all this with Panda3D 1.5.4 both on Windows and Ubuntu 8.04 (and I had that font at hand at the moment). I needed good looking text even with large zoom. Just put some other font in labelFont and you'll be OK... (i guess)
-
zzarko
-
- Posts: 14
- Joined: Mon Jun 30, 2008 11:25 am
by drwr » Thu Jan 22, 2009 4:28 pm
You can explicitly set the point size on "dynamic" fonts, which are .ttf files and what not. You can't set it on "static" fonts, which are .egg files or .bam files. So if you call:
- Code: Select all
font.setPointSize(10)
it might fail, according to what kind of font file you've got. This is why it's not a good idea to make this call directly; instead, use the pointSize = xx parameter to loader.loadFont(), which will properly ignore the setting if it can't be set.
Of course, the default point size is 10 anyway, so this is not a particularly useful call. All it's doing is making your code less portable.
David
-
drwr
-
- Posts: 11253
- Joined: Fri Feb 13, 2004 12:42 pm
- Location: Glendale, CA
Return to Code Snippets
Who is online
Users browsing this forum: No registered users and 0 guests
| | |