Game Development Community

PanoramaScreenshot()

by James Urquhart · in Torque Game Engine · 09/25/2004 (1:46 am) · 1 replies

This console function is located in game.cpp.

However, its logic seems to be horribly broken.

Lets start with the args :
ConsoleFunction( panoramaScreenShot, void, 3, 3, "(string file, string format)"
                "Take a panoramic screenshot.nn"
                "@param format This is either JPEG or PNG.")
{
   S32 numShots = 3;
   if (argc == 3)
      numShots = dAtoi(argv[2]);

This description is wholly inaccurate, and does not even mention the "numShots" variable.
In addition, argc will always equal 3; The check is not required.
Of course, it could be a simple addition error. Perhaps the max number of arguments is supposed to be 4, whilst the minimum is 3?

The code seems to grab the control object, and keep rotating it, taking screenshots along the way (telling the Canvas to render itself each time of course). However, it also appears to be in the same predicament.

In the loop...
...
      dSprintf(buffer, sizeof(buffer), "%s-%d.png", argv[1], i);
      ...
Unfortunatly, it seems that the whole point of the "format" specifier seems to have been flushed down the toilet somewhere.

if(!fStream.open(buffer, FileStream::Write))
      {   
         Con::printf("Failed to open file '%s'.", buffer);
...
Only gripe about this is that its "printf" instead of something more informative such as "errorf".

Moving on...
if ( dStrcmp( argv[2], "JPEG" ) == 0 )
		  bitmap.writeJPEG(fStream);
	  else if( dStrcmp( argv[2], "PNG" ) == 0)
		  bitmap.writePNG(fStream);
	  else
		  bitmap.writePNG(fStream);
argv[2] is already used for "numShots", so it can't possibly be used again for the format specifier. Unless of course, you made argv[3] "numShots".


Anyway, here's my corrected version :
ConsoleFunction( panoramaScreenShot, void, 3, 4, "(string file, string format, [int shots])"
                "Take a panoramic screenshot.nn"
                "@param format This is either JPEG or PNGn"
		 "@param shots Number of screenshots to take")
{
   S32 numShots = 3;
   if (argc == 4)
      numShots = dAtoi(argv[3]);
   
   // Should we write PNG or JPEG?
   bool writeJPEG = (dStrcmp( argv[2], "JPEG" )) ? false : true;

   CameraQuery query;
   if (!GameProcessCameraQuery( &query ))
      return;

   SceneObject *object = dynamic_cast<SceneObject*>(query.object);
   if (!object)
      return;

   F32 rotInc = query.fov * 0.75f;

   FileStream fStream;
   GBitmap bitmap;
   Point2I extent = Canvas->getExtent();
   bitmap.allocateBitmap(U32(extent.x), U32(extent.y));
   U8 * pixels = new U8[extent.x * extent.y * 3];

   
   S32 start = -(numShots/2);
   for (S32 i=0; i<numShots; i++, start++)
   {
      char buffer[256];

      MatrixF rot( EulerF(0.0f, 0.0f, rotInc * F32(start)) );
      MatrixF result;
      result.mul(query.cameraMatrix, rot);

      object->setTransform( result );
      Canvas->renderFrame(false);
      if (writeJPEG)
         dSprintf(buffer, sizeof(buffer), "%s-%d.jpg", argv[1], i);
      else
	 dSprintf(buffer, sizeof(buffer), "%s-%d.png", argv[1], i);

      glReadBuffer(GL_FRONT);
      glReadPixels(0, 0, extent.x, extent.y, GL_RGB, GL_UNSIGNED_BYTE, pixels);

      if(!fStream.open(buffer, FileStream::Write))
      {   
         Con::errorf("Failed to open file '%s'.", buffer);
         break;
      }
      
      // flip the rows
      for(U32 y = 0; y < extent.y; y++)
         dMemcpy(bitmap.getAddress(0, extent.y - y - 1), pixels + y * extent.x * 3, U32(extent.x * 3));
   
      if (writeJPEG)
         bitmap.writeJPEG(fStream);
      else
	 bitmap.writePNG(fStream);

      fStream.close();
   }

   delete [] pixels;
}

I did test out this ConsoleFunction, but it seems to generate a grey border round the image, for all the rotated images...
Does anyone know what program i am meant to plonk these images into?