Told you!...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
high resolution (I mean REALLY high)?
- raicuandi
- Gargoyle
- Posts: 1092
- Joined: Wed Nov 09, 2005 12:56 pm
- Location: Adelaide, Australia
- Contact:
-
- Halfling
- Posts: 42
- Joined: Mon Aug 08, 2005 12:09 pm
- Location: Paris
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
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
- DWORD
- OGRE Retired Moderator
- Posts: 1365
- Joined: Tue Sep 07, 2004 12:43 pm
- Location: Aalborg, Denmark
- Contact:
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.
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.
-
- Halfling
- Posts: 81
- Joined: Sat Jul 08, 2006 10:02 am
- Location: Texas, USA
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".
-
- Halfling
- Posts: 42
- Joined: Mon Aug 08, 2005 12:09 pm
- Location: Paris
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? ) could perhaps enhance the method by directly assembling the screenshots in the memory and saving only one big file?
Here is my code:
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? ) 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
}
- jacmoe
- OGRE Retired Moderator
- Posts: 20570
- Joined: Thu Jan 22, 2004 10:13 am
- Location: Denmark
- x 179
- Contact:
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.
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
- DWORD
- OGRE Retired Moderator
- Posts: 1365
- Joined: Tue Sep 07, 2004 12:43 pm
- Location: Aalborg, Denmark
- Contact:
-
- Halfling
- Posts: 42
- Joined: Mon Aug 08, 2005 12:09 pm
- Location: Paris
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.
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
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
- DWORD
- OGRE Retired Moderator
- Posts: 1365
- Joined: Tue Sep 07, 2004 12:43 pm
- Location: Aalborg, Denmark
- Contact:
Cool.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.
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:Well, I don't put an example here because not only the number of pixels, but also the file size grows.
Just imagine an oversize version of your own screens.
Code Snippets would be good place I think.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...
-
- Halfling
- Posts: 42
- Joined: Mon Aug 08, 2005 12:09 pm
- Location: Paris
I'll put it there, no problem.Code Snippets would be good place I think.
Ok ok, this is one of my plants:Could you post a normal sized screenshot, then (or convert to jpeg)?
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?
- DWORD
- OGRE Retired Moderator
- Posts: 1365
- Joined: Tue Sep 07, 2004 12:43 pm
- Location: Aalborg, Denmark
- Contact:
-
- Halfling
- Posts: 42
- Joined: Mon Aug 08, 2005 12:09 pm
- Location: Paris
Check out http://www.ogre3d.org/wiki/index.php/Hi ... creenshots , my fist contribution to the Ogre Wiki...
Everybody is invited to enhance it!
Everybody is invited to enhance it!
- DWORD
- OGRE Retired Moderator
- Posts: 1365
- Joined: Tue Sep 07, 2004 12:43 pm
- Location: Aalborg, Denmark
- Contact:
-
- Halfling
- Posts: 42
- Joined: Mon Aug 08, 2005 12:09 pm
- Location: Paris
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.
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.
-
- Halfling
- Posts: 81
- Joined: Sat Jul 08, 2006 10:02 am
- Location: Texas, USA
-
- Halfling
- Posts: 42
- Joined: Mon Aug 08, 2005 12:09 pm
- Location: Paris
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
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
-
- Gnome
- Posts: 375
- Joined: Sat Jul 16, 2005 1:42 am
- Location: Montreal
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
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
-
- Gnome
- Posts: 375
- Joined: Sat Jul 16, 2005 1:42 am
- Location: Montreal
I've fiddled around with the code and came up with this updated version:
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.
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;
}
}
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.
-
- Halfling
- Posts: 42
- Joined: Mon Aug 08, 2005 12:09 pm
- Location: Paris
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.
Stefan
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.
Stefan
-
- Gnome
- Posts: 375
- Joined: Sat Jul 16, 2005 1:42 am
- Location: Montreal
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).
- Praetor
- OGRE Retired Team Member
- Posts: 3335
- Joined: Tue Jun 21, 2005 8:26 pm
- Location: Rochester, New York, US
- x 3
- Contact:
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.
The little box is the sub-scene. Fill in the rows to the right with blanks, knowing you'll fill it in later.
Code: Select all
------------------------------------------------------------------
| | |
| | |
| | |
|___________| |
| |
| |
|______________________________________________|
- wilford
- Gnoblar
- Posts: 9
- Joined: Thu Dec 21, 2006 6:27 am
- Location: ChengDu,SiChuan,China
- Contact:
-
- Gnome
- Posts: 375
- Joined: Sat Jul 16, 2005 1:42 am
- Location: Montreal
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:
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.
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;
}
}
I hope this made sense.
- wilford
- Gnoblar
- Posts: 9
- Joined: Thu Dec 21, 2006 6:27 am
- Location: ChengDu,SiChuan,China
- Contact:
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:
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.
At first,my code is like this:
Code: Select all
frameStarted()
{
if(mInputDevice->isKeyDown(KC_B))
{
gridScreenshots(3);
}
}
Now it's all right.
Finally,I got a screenshot, but the window frame is still within.