Kaynağa Gözat

add saveCubemap(); robustify screenshot methods

David Rose 20 yıl önce
ebeveyn
işleme
b044a473b9
1 değiştirilmiş dosya ile 99 ekleme ve 27 silme
  1. 99 27
      direct/src/showbase/ShowBase.py

+ 99 - 27
direct/src/showbase/ShowBase.py

@@ -1530,59 +1530,131 @@ class ShowBase(DirectObject.DirectObject):
         if self.camFrustumVis:
         if self.camFrustumVis:
             self.camFrustumVis.removeNode()
             self.camFrustumVis.removeNode()
 
 
-    def screenshot(self, namePrefix='screenshot'):
-        filename = self.win.saveScreenshotDefault(namePrefix)
-        if filename.empty():
-            # The screenshot attempt failed for some reason.
-            return 0
+    def screenshot(self, namePrefix = 'screenshot',
+                   defaultFilename = 1, source = None):
+        """ Captures a screenshot from the main window or from the
+        specified window or Texture and writes it to a filename in the
+        current directory (or to a specified directory).
+
+        If defaultFilename is True, the filename is synthesized by
+        appending namePrefix to a default filename suffix (including
+        the filename extension) specified in the Config variable
+        screenshot-filename.  Otherwise, if defaultFilename is False,
+        the entire namePrefix is taken to be the filename to write,
+        and this string should include a suitable filename extension
+        that will be used to determine the type of image file to
+        write.
+
+        Normally, the source is a GraphicsWindow, GraphicsBuffer or
+        DisplayRegion.  If a Texture is supplied instead, it must have
+        a ram image (that is, if it was generated by
+        makeTextureBuffer() or makeCubeMap(), the parameter toRam
+        should have been set true).  If it is a cube map texture as
+        generated by makeCubeMap(), namePrefix should contain the hash
+        mark ('#') character. """
+        
+        if source == None:
+            source = self.win
+
+        if defaultFilename:
+            filename = GraphicsOutput.makeScreenshotFilename(namePrefix)
+        else:
+            filename = Filename(namePrefix)
+
+        if isinstance(source, Texture):
+            if source.getZSize() > 1:
+                saved = source.writePages(filename)
+            else:
+                saved = source.write(filename)
+        else:
+            saved = source.saveScreenshot(filename)
 
 
         # Announce to anybody that a screenshot has been taken
         # Announce to anybody that a screenshot has been taken
         messenger.send('screenshot', [filename])
         messenger.send('screenshot', [filename])
-        return 1
+
+        return saved
+
+    def saveCubemap(self, namePrefix = 'cubemap_#.png',
+                    defaultFilename = 0, source = None,
+                    camera = None, size = 128,
+                    cameraMask = BitMask32.allOn()):
+
+        """ Similar to screenshot(), this sets up a temporary cube map
+        Texture which it uses to take a series of six snapshots of the
+        current scene, one in each of the six cube map directions.
+        This requires rendering a new frame.
+
+        Unlike screenshot(), source may only be a GraphicsWindow,
+        GraphicsBuffer, or DisplayRegion; it may not be a Texture.
+
+        camera should be the node to which the cubemap cameras will be
+        parented.  The default is the camera associated with source,
+        if source is a DisplayRegion, or base.camera otherwise."""
+
+        if source == None:
+            source = base.win
+
+        if camera == None:
+            if hasattr(source, "getCamera"):
+                camera = source.getCamera()
+            if camera == None:
+                camera = base.camera
+
+        if hasattr(source, "getWindow"):
+            source = source.getWindow()
+
+        rig = NodePath(namePrefix)
+        buffer = source.makeCubeMap(namePrefix, size, 1, rig, cameraMask)
+        if buffer == None:
+            raise StandardError, "Could not make cube map."
+
+        # Now render a frame to fill up the texture.
+        rig.reparentTo(camera)
+        base.graphicsEngine.renderFrame()
+
+        tex = buffer.getTexture()
+        saved = self.screenshot(namePrefix = namePrefix,
+                                defaultFilename = defaultFilename,
+                                source = tex)
+
+        base.graphicsEngine.removeWindow(buffer)
+        rig.removeNode()
+
+        return saved
 
 
     def movie(self, namePrefix = 'movie', duration = 1.0, fps = 30,
     def movie(self, namePrefix = 'movie', duration = 1.0, fps = 30,
-              format = 'rgb', sd = 4, source = None):
+              format = 'png', sd = 4, source = None):
         """
         """
-        movie(namePrefix = 'movie', duration=1.0, fps=30, format='rgb', sd=4)
-
         Spawn a task to capture a movie using the screenshot function.
         Spawn a task to capture a movie using the screenshot function.
         - namePrefix will be used to form output file names (can include
         - namePrefix will be used to form output file names (can include
           path information (e.g. '/i/beta/frames/myMovie')
           path information (e.g. '/i/beta/frames/myMovie')
         - duration is the length of the movie in seconds
         - duration is the length of the movie in seconds
         - fps is the frame rate of the resulting movie
         - fps is the frame rate of the resulting movie
-        - format specifies output file format (e.g. rgb, bmp)
+        - format specifies output file format (e.g. png, bmp)
         - sd specifies number of significant digits for frame count in the
         - sd specifies number of significant digits for frame count in the
-          output file name (e.g. if sd = 4, movie_0001.rgb)
+          output file name (e.g. if sd = 4, movie_0001.png)
         - source is the Window, Buffer, DisplayRegion, or Texture from which
         - source is the Window, Buffer, DisplayRegion, or Texture from which
           to save the resulting images.  The default is the main window.
           to save the resulting images.  The default is the main window.
         """
         """
-        if source == None:
-            source = self.win
         globalClock.setMode(ClockObject.MNonRealTime)
         globalClock.setMode(ClockObject.MNonRealTime)
         globalClock.setDt(1.0/float(fps))
         globalClock.setDt(1.0/float(fps))
         t = taskMgr.add(self._movieTask, namePrefix + '_task')
         t = taskMgr.add(self._movieTask, namePrefix + '_task')
-        t.endT = globalClock.getFrameTime() + duration
         t.frameIndex = 1
         t.frameIndex = 1
+        t.numFrames = int(duration * fps)
         t.source = source
         t.source = source
         t.outputString = namePrefix + '_%0' + `sd` + 'd.' + format
         t.outputString = namePrefix + '_%0' + `sd` + 'd.' + format
         t.uponDeath = lambda state: globalClock.setMode(ClockObject.MNormal)
         t.uponDeath = lambda state: globalClock.setMode(ClockObject.MNormal)
 
 
     def _movieTask(self, state):
     def _movieTask(self, state):
-        currT = globalClock.getFrameTime()
-        if currT >= state.endT:
+        frameName = state.outputString % state.frameIndex
+        self.notify.info("Capturing frame: " + frameName)
+        self.screenshot(namePrefix = frameName, defaultFilename = 0,
+                        source = state.source)
+                
+        state.frameIndex += 1
+        if state.frameIndex > state.numFrames:
             return Task.done
             return Task.done
         else:
         else:
-            frameName = state.outputString % state.frameIndex
-            self.notify.info("Capturing frame: " + frameName)
-            if isinstance(state.source, Texture):
-                if state.source.getZSize() > 1:
-                    state.source.writePages(HashFilename(frameName))
-                else:
-                    state.source.write(Filename(frameName))
-            else:
-                state.source.saveScreenshot(Filename(frameName))
-                
-            state.frameIndex += 1
             return Task.cont
             return Task.cont
 
 
     def __windowEvent(self, win):
     def __windowEvent(self, win):