high resolution (I mean REALLY high)?

Anything and everything that's related to OGRE or the wider graphics field that doesn't fit into the other forums.
User avatar
raicuandi
Gargoyle
Posts: 1092
Joined: Wed Nov 09, 2005 12:56 pm
Location: Adelaide, Australia
Contact:

Post by raicuandi »

sbornhof wrote:It's solved. The external window I created had outer dimensions of 640*480, but inner dimensions of only 632*446.

Thanks again.

Stefan
Told you!... :wink:
sbornhof
Halfling
Posts: 42
Joined: Mon Aug 08, 2005 12:09 pm
Location: Paris

Post by sbornhof »

I've spent some time with thinking about how to manipulate the frustum in order to get a partial view like DWORD suggested.

However, I have to admit that I even don't understand which functions could do the trick. mCamera->setFOVy() might be used to reduce the frustum size, but how can I shift it into the upper left corner?

Stefan
User avatar
DWORD
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 1365
Joined: Tue Sep 07, 2004 12:43 pm
Location: Aalborg, Denmark
Contact:

Post by DWORD »

I think you need to set the projection matrix manually, check out Frustum::setCustomProjectionMatrix.

The matrix you want to use as far as I could find out is an 'asymmetrical perspective projection matrix'. Maybe you can dig up the actual calculations on google.
KeAz
Halfling
Posts: 81
Joined: Sat Jul 08, 2006 10:02 am
Location: Texas, USA

Post by KeAz »

Wow, This sounds like a good project. I'd like to se the finished results. I could possibly use it for making something like a 360 degree panaramic. Which could be printed all the way around a T-shirt or mug or the like. I've seen this done with real photos before and it works very well, but has stitching issues. In the virtual enviroment it could be calculated and made "picture perfect".
sbornhof
Halfling
Posts: 42
Joined: Mon Aug 08, 2005 12:09 pm
Location: Paris

Post by sbornhof »

I did it!

DWORD , thanks again for your help. As a matter of fact, there is a page http://www.cs.kuleuven.ac.be/cwis/resea ... node8.html which sufficiently explains the setup of asymmetrical perspective projections.

So I wrote a method "gridScreenshots(int gridSize)" which subdivides the screen into gridSize*gridSize subscreens (in the order from the upper left corner to the lower right corner, by setting up the corresponding projection matrices) and saves the resulting screenshots to the hard drive.

I patched the screenshots together in a paint program, it works fine for me! Try out if it works in other applications. Someone who is more experienced with Ogre code (raicuandi? :D ) could perhaps enhance the method by directly assembling the screenshots in the memory and saving only one big file?

Here is my code:

Code: Select all

void OgreViewer::gridScreenshots(int gridSize)
{
	mCamera->setCustomProjectionMatrix(false); // reset projection matrix
	Ogre::Matrix4 standard = mCamera->getProjectionMatrix();
	double nearDist = mCamera->getNearClipDistance();
	double nearWidth = (mCamera->getWorldSpaceCorners()[0] - mCamera->getWorldSpaceCorners()[1]).length();
	double nearHeight = (mCamera->getWorldSpaceCorners()[1] - mCamera->getWorldSpaceCorners()[2]).length();
	int nbScreenshots = 0;

	for (int n=0;n<gridSize*gridSize;n++)
	{
		// use asymmetrical perspective projection.
		// check out http://www.cs.kuleuven.ac.be/cwis/research/graphics/INFOTEC/viewing-in-3d/node8.html for more explanations
		int y = n / gridSize;
		int x = n - y * gridSize;
		Ogre::Matrix4 shearing(
			1,0,(x-(gridSize-1)*0.5)*nearWidth/nearDist,0, 
			0,1,-(y-(gridSize-1)*0.5)*nearHeight/nearDist,0, 
			0,0,1,0,
			0,0,0,1);
		Ogre::Matrix4 scale(
			gridSize,0,0,0,
			0,gridSize,0,0, 
			0,0,1,0,
			0,0,0,1);
		mCamera->setCustomProjectionMatrix(true,standard*shearing*scale);
		mRoot->renderOneFrame();
		mWindow->writeContentsToFile(Ogre::String("gridscreenshot")+ Ogre::StringConverter::toString(nbScreenshots++) + Ogre::String(".png"));
	}
	mCamera->setCustomProjectionMatrix(false); // reset projection matrix
}
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Post by jacmoe »

Consider putting this in the Ogre Wiki (high-res screenshot?) - then I am pretty sure people will help improve it. :)
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
User avatar
DWORD
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 1365
Joined: Tue Sep 07, 2004 12:43 pm
Location: Aalborg, Denmark
Contact:

Post by DWORD »

Cool, good to see you made it, and yes a wiki entry would be good to have. :)

Which resolution did you manage to make the screenshot? And can we by any chance get a sneak peek? :P
sbornhof
Halfling
Posts: 42
Joined: Mon Aug 08, 2005 12:09 pm
Location: Paris

Post by sbornhof »

I used a resolution of 640*480 and tested up to a 7*7 grid, which yielded a perfect 4480*3360 pixel screenshot. Well, I don't put an example here because not only the number of pixels, but also the file size grows. :D
Just imagine an oversize version of your own screens.

Yes, why not put it into the Ogre Wiki, but can you suggest me where the subject fits best? There are so many categories...

Stefan
User avatar
DWORD
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 1365
Joined: Tue Sep 07, 2004 12:43 pm
Location: Aalborg, Denmark
Contact:

Post by DWORD »

sbornhof wrote:I used a resolution of 640*480 and tested up to a 7*7 grid, which yielded a perfect 4480*3360 pixel screenshot.
Cool.
sbornhof wrote:Well, I don't put an example here because not only the number of pixels, but also the file size grows. :D
Just imagine an oversize version of your own screens.
Yes, but then I'd rather imagine an oversize version of your screenshots as the project sounded interesting. Could you post a normal sized screenshot, then (or convert to jpeg)? :)
sbornhof wrote:Yes, why not put it into the Ogre Wiki, but can you suggest me where the subject fits best? There are so many categories...
Code Snippets would be good place I think.
sbornhof
Halfling
Posts: 42
Joined: Mon Aug 08, 2005 12:09 pm
Location: Paris

Post by sbornhof »

Code Snippets would be good place I think.
I'll put it there, no problem.
Could you post a normal sized screenshot, then (or convert to jpeg)?
Ok ok, this is one of my plants:

Image

These virtual creatures grow in a simplified environment providing light and minerals. They start as a seed, then capture resources in order to develop leaves, branches and roots. Their growth is ruled by a set of genetic information. For my PhD, I let those plants evolve - the scientific domain is called "Artificial Life". Do you like it?
User avatar
DWORD
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 1365
Joined: Tue Sep 07, 2004 12:43 pm
Location: Aalborg, Denmark
Contact:

Post by DWORD »

sbornhof wrote:Do you like it?
Yes! :P Thanks for the view.
sbornhof
Halfling
Posts: 42
Joined: Mon Aug 08, 2005 12:09 pm
Location: Paris

Post by sbornhof »

Check out http://www.ogre3d.org/wiki/index.php/Hi ... creenshots , my fist contribution to the Ogre Wiki... 8)
Everybody is invited to enhance it!
User avatar
DWORD
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 1365
Joined: Tue Sep 07, 2004 12:43 pm
Location: Aalborg, Denmark
Contact:

Post by DWORD »

Hey, that's nice. :D
KeAz
Halfling
Posts: 81
Joined: Sat Jul 08, 2006 10:02 am
Location: Texas, USA

Post by KeAz »

Yes, very nice. Is there anyway I could convince you to share your program? This is a very interesting project with many possible applications. Maybe when your finished with it?
sbornhof
Halfling
Posts: 42
Joined: Mon Aug 08, 2005 12:09 pm
Location: Paris

Post by sbornhof »

Thanks for your interest! I think, the project is never really "finished" and can always be enriched by new aspects. For example, I currently simulate plant growth depending on two resources (light and minerals), but next month I will add virtual water to the model and study plant responses to drought.
So far, I mainly addressed scientific issues, but I am very interested in other applications. For example, I once evolved strange-looking extraterrestrial plants by simple aesthetic criteria (see the picture below). So don't hesitate to contact me if you like to integrate a model of adaptive plants into your virtual worlds. :D

Image
KeAz
Halfling
Posts: 81
Joined: Sat Jul 08, 2006 10:02 am
Location: Texas, USA

Post by KeAz »

I'm interested to so how you did it because, while I would not be using it for purely scientific reasons. I was hoping to adapt it for world/landscape building for gaming purposes(with full credit for any direct adaptation). I have grand plans and they are slowly taking shape.
sbornhof
Halfling
Posts: 42
Joined: Mon Aug 08, 2005 12:09 pm
Location: Paris

Post by sbornhof »

Hello,

I am reviving this thread because I'd really like to settle the question of creating large size OGRE screenshots.

As you can read in the previous posts, I managed to write a method which divides the screen into subscreens and saves the individual subscreenshots to the hard drive. It remains the problem of automatically assembling the subscreenshots to a big image. Although the corresponding Wiki page http://www.ogre3d.org/wiki/index.php/Hi ... creenshots has been visited about 2000 times, no solution was proposed so far.

Do you think that the method RenderTarget::writeContentsToFile(...) could be enhanced? Or does anybody have a code snippet which stitches together image files?

Thanks for you help!

Stefan
Rackle
Gnome
Posts: 375
Joined: Sat Jul 16, 2005 1:42 am
Location: Montreal

Post by Rackle »

Just throwing an idea around, hopefully to be built upon.

If an uncompressed bitmap is generated, one where each pixel is defined, then it's not too complicated to manually stitch them. Then the problem becomes one of compressing that very large bitmap.

So what's really needed is a way to convert each Ogre screenshot image into an uncompressed bitmap, stitch the bitmaps together, and finally convert that huge uncompressed bitmap into a more useful image file.

http://en.wikipedia.org/wiki/Image_stitching
Rackle
Gnome
Posts: 375
Joined: Sat Jul 16, 2005 1:42 am
Location: Montreal

Post by Rackle »

I've fiddled around with the code and came up with this updated version:

Code: Select all

void gridScreenshots(Ogre::Camera* camera, const int& gridSize, const Ogre::String& fileName, const Ogre::String& fileExtention, const bool& stitchGridImages)
{
	camera->setCustomProjectionMatrix(false); // reset projection matrix
	Ogre::Matrix4 standard = camera->getProjectionMatrix();
	double nearDist = camera->getNearClipDistance();
	double nearWidth = (camera->getWorldSpaceCorners()[0] - camera->getWorldSpaceCorners()[1]).length();
	double nearHeight = (camera->getWorldSpaceCorners()[1] - camera->getWorldSpaceCorners()[2]).length();
	Ogre::Image sourceImage;
	Ogre::String gridFilename;
	Ogre::uchar* stitchedImageData;
	int nbScreenshots = 0;

	for (int n = 0; n < gridSize * gridSize; n++) 
	{ 
		// Use asymmetrical perspective projection. For more explanations check out:
		// http://www.cs.kuleuven.ac.be/cwis/research/graphics/INFOTEC/viewing-in-3d/node8.html 
		int y = n / gridSize; 
		int x = n - y * gridSize; 
		Ogre::Matrix4 shearing( 
			1, 0,(x - (gridSize - 1) * 0.5) * nearWidth / nearDist, 0, 
			0, 1, -(y - (gridSize - 1) * 0.5) * nearHeight / nearDist, 0, 
			0, 0, 1, 0, 
			0, 0, 0, 1); 
		Ogre::Matrix4 scale( 
			gridSize, 0, 0, 0, 
			0, gridSize, 0, 0, 
			0, 0, 1, 0, 
			0, 0, 0, 1); 
		camera->setCustomProjectionMatrix(true, standard * shearing * scale);
		Ogre::Root::getSingletonPtr()->renderOneFrame();
		gridFilename = fileName + Ogre::StringConverter::toString(nbScreenshots++) + fileExtention;
		Ogre::Root::getSingletonPtr()->getAutoCreatedWindow()->writeContentsToFile(gridFilename);

		if(stitchGridImages)
		{
			sourceImage.load(gridFilename, "General");
			Ogre::ColourValue colourValue;
			int stitchedX, stitchedY, stitchedIndex;
			if(n == 0)
				stitchedImageData = new Ogre::uchar[sourceImage.getWidth() * gridSize * sourceImage.getHeight() * gridSize * 3]; // 3 colors per pixel
			for(int rawY = 0; rawY < (int) sourceImage.getHeight(); rawY++)
			{
				for(int rawX = 0; rawX < (int) sourceImage.getWidth(); rawX++)
				{
					colourValue = sourceImage.getColourAt(rawX, rawY, 0);
					stitchedY = y * (int) sourceImage.getHeight() + rawY;
					stitchedX = x * (int) sourceImage.getWidth() + rawX;
					stitchedIndex = stitchedY * (int) sourceImage.getWidth() * gridSize + stitchedX;
					Ogre::PixelUtil::packColour(sourceImage.getColourAt(rawX, rawY, 0),
						Ogre::PF_R8G8B8,
						(void*) &stitchedImageData[stitchedIndex * 3]);
				}
			}
		}
	} 
	camera->setCustomProjectionMatrix(false); // reset projection matrix 

	if(stitchGridImages)
	{
		Ogre::Image targetImage;
		targetImage.loadDynamicImage(stitchedImageData,
									sourceImage.getWidth() * gridSize,
									sourceImage.getHeight() * gridSize,
									1, // depth
									Ogre::PF_R8G8B8,
									false);
		targetImage.save(fileName + fileExtention);
		delete[] stitchedImageData;
	}
}
Stitching is working fine for fullscreen DirectX but not for the other configurations.

Windowed DirectX: writeContentsToFile() includes the title and border of the window.

Fullscreen OpenGL: screenshot 0 is performed without matrix transformation and is out of sequence. Something very funky is going on; 1 should be 0, 2 should be 1, etc. There is a black line around the screenshots, which do not appear under DirectX. Most likely a rounding artifact

Windowed OpenGL: the stitching worked correctly but there are still black lines around the screenshots.

My video card is an NVIDIA GeForce 6800 GS, DirectX v9.0C but I'm not sure how to check the version of OpenGL.

This version simply takes each file generated from writeContentsToFile(), loads it, puts it into a memory buffer, and finally saves this new image. A better/faster approach would be to bypass the calls to writeContentsToFile() and Image::load() and directly build the final image in memory. However I'm unsure how to go about doing that.
sbornhof
Halfling
Posts: 42
Joined: Mon Aug 08, 2005 12:09 pm
Location: Paris

Post by sbornhof »

I equally worked on a solution and eventually coded a method like yours, Rackle, which reloads the captured screenshots, copies the whole series into a huge memory buffer, and saves the data as a bitmap into a final file. By doing so, I managed to stitch a neat 12000 x 9000 pixel bmp, but my poor computer was reaching its limits...

However, my solution does not use OGRE related classes/methods any more, but HBITMAP, HDC and BitBlt. As Rackle said, it would be much smarter to bypass the method writeContentsToFile(), but never mind for now. Perhaps a future version of OGRE will feature an enhanced writeContentsToFile(int n) where n ist the desired multiple of the screensize. :wink:

Stefan
Rackle
Gnome
Posts: 375
Joined: Sat Jul 16, 2005 1:42 am
Location: Montreal

Post by Rackle »

My feature request would be for a new function to be created, such as Ogre::Image getContents(). This would allow applications to retrieve the contents of the front buffer and do whatever they want, either to save to a file or to manipulate in any other way. However I'm not completely done with this topic yet. I just need to give it some time, to search for a different way to access that front buffer (I'm probably not using the correct term though).
User avatar
Praetor
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 3335
Joined: Tue Jun 21, 2005 8:26 pm
Location: Rochester, New York, US
x 3
Contact:

Post by Praetor »

A streaming solution might be the way to go. It would be quite complicated file manipulation. Render the sub-screen into a buffer. Now, open the file and save this file out, but do so as to preserve the final positioning of the file. That means you would have write out this piece with blanks in rows and columns planning on filling them in later with the other sub-scenes.

Code: Select all

------------------------------------------------------------------
|                   |                                                            |
|                   |                                                            |
|                   |                                                            |
|___________|                                                            |
|                                                                                |
|                                                                                |
|______________________________________________|    
The little box is the sub-scene. Fill in the rows to the right with blanks, knowing you'll fill it in later.
User avatar
wilford
Gnoblar
Posts: 9
Joined: Thu Dec 21, 2006 6:27 am
Location: ChengDu,SiChuan,China
Contact:

Post by wilford »

Hello,I'm a novice.I don't know the principle of this code snippet.Now I just want to use it.But the stack overflowed at the line mRoot->renderOneFrame();.I tried to invoke other methods of mRoot,it worked fine.I'm wondering why.
Rackle
Gnome
Posts: 375
Joined: Sat Jul 16, 2005 1:42 am
Location: Montreal

Post by Rackle »

Do you have keyboard-handling code within frameStarted() or frameEnded() ? Maybe you are calling the screenshot function multiple time, which calls renderOneFrame(), which would then call frameStarted() and frameEnded(), which would call the screenshot function again, and so on until you get a stack overflow.

In that case you could change your code to something like that:

Code: Select all

frameStarted()
{
  if(keypressed == screenshot_key && takingScreenshot == false)
  {
    takingScreenshot = true;
    gridScreenshots();
    takingScreenshot = false;
  }
}
However I'd prefer to really separate the code: doing input handling somewhere else and limiting the code within frameStarted() to whatever needs to be done for that frame; handling input each frame for an application running at 100 frames per second is too much.

I hope this made sense.
User avatar
wilford
Gnoblar
Posts: 9
Joined: Thu Dec 21, 2006 6:27 am
Location: ChengDu,SiChuan,China
Contact:

Post by wilford »

Thank you,Rackle.With your help,I solved it at last.And thanks to sbornhof,the code is cool.

At first,my code is like this:

Code: Select all

frameStarted() 
{ 
  if(mInputDevice->isKeyDown(KC_B)) 
  { 
    gridScreenshots(3); 
  } 
} 
There is no flag to prevent multiple invoking,so stack overflowed.
Now it's all right.

Finally,I got a screenshot, but the window frame is still within.
Image
Post Reply