static 3d scene with working directGUI [nearly SOLVED]

I want to render (just ONCE not each frame) a static 3d scene and then idle while the user is using the directGUI user interface, certain UI actions will cause the texture to be re-rendered with the camera in a new location.

I’m making a RPG game but for very low hardware requirement, although panda3d is generally impressive with my eeePC, running at low throttle (800mhz) between the two threads about 25-30% of cpu time is being used for directGUI alone and I want to minimise the impact on the battery and also allow even lower hardware specs to be able to run what is basically a turn based game with nice 3d static pictures.

I’m not exactly sure of the best method to achieve this, is there a way to avoid the main loop and just call render for an offscreen buffer when you need to?

I may also allow a user configurable option to allow basic 3d idle animations say a frame every .25 of a second when you have mains! :open_mouth:

This sort of set up would be rather useful for not only netbooks but also for beagle board based systems like the openpandora (which is finally looking none vaporware YaY!)
how hard can an arm port be :wink:

TIA

You can call base.graphicsEngine.renderFrame() twice (first time to render the frame, the second time to flip the buffer), perform loading routines, and start the main loop afterwards.

I’ve already got Panda3D running on my beagle board. :wink:

I’m not understanding this obviously, as soon as the main loop starts the 3d scenenode will be getting rendered each frame won’t it?

ok here’s a stripped down version of the teapot sample that
nearly does what I want!

However when you press v notice the teapot is always animated

what I want to happen is only process a frame when g is pressed - not sure how I can better describe what I’m after!

see below

slightly buggy but does what I want!

only problem is updating the “animation” can be erratic just occasionally it will jump twice for one key press…

#!/usr/bin/python
import direct.directbase.DirectStart

from panda3d.core import Filename,Texture
from panda3d.core import AmbientLight,DirectionalLight
from panda3d.core import NodePath,TextNode
from panda3d.core import Point3,Vec3,Vec4,BillboardEffect  
from direct.task.Task import Task
from direct.actor.Actor import Actor
from direct.gui.OnscreenText import OnscreenText
from direct.showbase.DirectObject import DirectObject
from panda3d.core import GraphicsOutput
from direct.gui.DirectGui import *

import sys,os,random

class MyDemo(DirectObject):
   def __init__(self):
      self.texOsb = Texture()
      self.OsBuffer=base.win.makeTextureBuffer("offscreen buffer", 128, 128)
      self.OsBuffer.addRenderTexture(self.texOsb, GraphicsOutput.RTMTriggeredCopyTexture)
      self.OsRender=NodePath("offscreen renderer")
      base.setBackgroundColor(0,0,0,1)

      self.OsCam=base.makeCamera(self.OsBuffer)
      self.OsCam.reparentTo(self.OsRender)        
      self.OsCam.setPos(0,-10,0)

      self.teapot=loader.loadModel('models/teapot')
      self.teapot.reparentTo(self.OsRender)
      self.teapot.setPos(0,0,-2)
      #self.teapot.hprInterval(1,Point3(360,360,360)).loop()

      dlight = DirectionalLight('dlight')
      alight = AmbientLight('alight')
      dlnp = self.OsRender.attachNewNode(dlight) 
      alnp = self.OsRender.attachNewNode(alight)
      dlight.setColor(Vec4(0.8, 0.2, 0.2, 1))
      alight.setColor(Vec4(0.2, 0.2, 0.2, 1))
      dlnp.setHpr(0, -60, 0) #!!! todo
      self.OsRender.setLight(dlnp)
      self.OsRender.setLight(alnp)
      
      self.accept("v", base.bufferViewer.toggleEnable)
      self.accept("V", base.bufferViewer.toggleEnable)
      base.bufferViewer.setPosition("llcorner")
      base.bufferViewer.setCardSize(1.0, 0.0)
        
      self.accept("escape", sys.exit, [0]) 
      
      self.accept("g", self.grab)
      self.accept("G", self.grab)
      
      self.txtPlane = loader.loadModel('samples/Texture-Swapping/models/plane')
      self.txtPlane.setPos(0, 8, 1.5)         #set its position
      self.txtPlane.reparentTo(render)       #reparent to render
      self.txtPlane.setTexture(self.texOsb)
      
      self.OsBuffer.setActive(True)
      self.sleepNextFrame=True
      taskMgr.add(self.sleeperTask,"sleeper task")
      
   def grab(self):
      self.OsBuffer.triggerCopy()
      self.OsBuffer.setActive(True)

      
   def sleeperTask(self,task):

      # we have to do "animations" manually as no longer "realtime"
      # need to find a better place for this......
      # camera move in response to UI etc....
      self.teapot.setH(self.teapot.getH()+0.017453293*36)
      
      if (self.sleepNextFrame==False and self.OsBuffer.isActive()):
         self.sleepNextFrame=True
         return task.cont
         
      if (self.sleepNextFrame==True):
         self.sleepNextFrame=False   
         self.OsBuffer.setActive(False)
         return task.cont
      return task.cont
              
md=MyDemo()
run()