Here is a hacked snippet that renders the scene into a texture buffer and saves that buffer to a jpeg every now and then. The jpegs are send out as an mjpeg stream which kann be viewed by a lot of browsers without plugin or with Vlc-player. over network. Its an mjpeg server. The server can also serve jpeg files or html files.
To open the stream in browser or vlc-player, open the url: localhost:8080/something.mjpeg
Actually the speed is quite descent. If someone has an idea to make it faster they are very welcome.
Here is the snippet:
from math import pi, sin, cos
from direct.directbase.DirectStart import *
from panda3d.core import *
import string,cgi,time
from os import curdir, sep
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from SocketServer import ThreadingMixIn
import re
count=0
global imgdata
global cameraQuality
cameraQuality=50
class MyHandler(BaseHTTPRequestHandler):
def do_GET(self):
global imgdata,count,cameraQuality
try:
self.path=re.sub('[^.a-zA-Z0-9]', "",str(self.path))
if self.path=="" or self.path==None or self.path[:1]==".":
return
if self.path.endswith(".html"):
f = open(curdir + sep + self.path)
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(f.read())
f.close()
return
if self.path.endswith(".mjpeg"):
self.send_response(200)
self.wfile.write("Content-Type: multipart/x-mixed-replace; boundary=--aaboundary")
self.wfile.write("\r\n\r\n")
while 1:
JpegData=imgdata
countval=count
self.wfile.write("--aaboundary\r\n")
self.wfile.write("Content-Type: image/jpeg\r\n")
self.wfile.write("Content-length: "+str(len(JpegData))+"\r\n\r\n" )
self.wfile.write(JpegData)
self.wfile.write("\r\n\r\n\r\n")
while countval==count:
time.sleep(0.01)
return
if self.path.endswith(".jpeg"):
f = open(curdir + sep + self.path)
self.send_response(200)
self.send_header('Content-type','image/jpeg')
self.end_headers()
self.wfile.write(f.read())
f.close()
return
return
except IOError:
self.send_error(404,'File Not Found: %s' % self.path)
def do_POST(self):
global rootnode , cameraQuality
try:
ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
if ctype == 'multipart/form-data':
query=cgi.parse_multipart(self.rfile, pdict)
self.send_response(301)
self.end_headers()
upfilecontent = query.get('upfile')
print "filecontent", upfilecontent[0]
value=int(upfilecontent[0])
cameraQuality=max(2, min(99, value))
self.wfile.write("<HTML>POST OK. Camera Set to<BR><BR>");
self.wfile.write(str(cameraQuality));
except :
pass
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
#class ThreadedHTTPServer(HTTPServer):
"""Handle requests in a separate thread."""
tex = Texture('tex')
def makepic(task):
global tex,imgdata,count
if not tex.hasRamImage():
return task.cont
pnmbimg=PNMImage()
ss=StringStream()
tex.store(pnmbimg)
pnmbimg.write(ss,"test.jpeg")
imgdata=ss.getData()
count=count^1
return task.again
mybuffer = base.win.makeTextureBuffer("My Buffer", 640, 480, tex, True)
mybuffer.setSort(-100)
mycamera = base.makeCamera(mybuffer)
myscene = NodePath("My Scene")
mycamera.reparentTo(myscene)
m = loader.loadModel('environment.egg')
m.reparentTo(myscene)
m.setPos(0, 0, 0)
sm = loader.loadModel('box.egg')
sm.reparentTo(myscene)
sm.setPos(0, 0, 0)
sm.setScale(2)
myInterval4 = sm.hprInterval(8.0, Vec3(360, 360, 0))
myInterval4.loop()
cm = CardMaker('card')
cm.setFrame(-1.0, 1.0, -1.0, 1.0)
card = aspect2d.attachNewNode(cm.generate())
card.setTexture(tex)
import thread
def handleserver():
global MyHandler
try:
server = ThreadedHTTPServer(('localhost', 8080), MyHandler)
print 'started httpserver...'
#thread.start_new_thread(pandathread,())
server.serve_forever()
except KeyboardInterrupt:
print '^C received, shutting down server'
server.socket.close()
thread.start_new_thread(handleserver,())
# Define a procedure to move the camera.
def spinCameraTask(task):
global mycamera,cv,server,cameraQuality,sm
angleDegrees = task.time * 6.0
angleRadians = angleDegrees * (pi / 180.0)
mycamera.setPos(20 * sin(angleRadians), -20.0 * cos(angleRadians), 3)
mycamera.setHpr(angleDegrees, 0, 0)
sm.setZ(cameraQuality/10.0)
return task.cont
taskMgr.add(spinCameraTask, "SpinCameraTask")
taskMgr.doMethodLater(0.1, makepic, 'TakeScene snapshot')
run()