Idea: Calculate Max Pixel Count for HOQs
-
- Gnoll
- Posts: 696
- Joined: Sun Feb 20, 2005 5:28 am
- Contact:
Idea: Calculate Max Pixel Count for HOQs
This should be an easy project for a student.
Utilize the HOQ Wiki Entry http://www.ogre3d.org/wiki/index.php/Ha ... ixel_Count to design an algorithm that can estimate the pixel count for an Ogre::Billboard at various resolutions and camera field of views.
Utilize the HOQ Wiki Entry http://www.ogre3d.org/wiki/index.php/Ha ... ixel_Count to design an algorithm that can estimate the pixel count for an Ogre::Billboard at various resolutions and camera field of views.
-
- Greenskin
- Posts: 103
- Joined: Sat Jul 24, 2004 7:06 pm
Why would you use an occlusion query on a billboard? You can just run the vertices through the current projection matrix and then do a simple formula to get the area in normalised screen coordinates (which you can easily change to # of pixels, or leave it as a ratio of total screen area, which is probably what you wanted in the first place.)
-
- Google Summer of Code Student
- Posts: 78
- Joined: Tue Mar 29, 2005 3:35 pm
- Location: USA
- Kencho
- OGRE Retired Moderator
- Posts: 4011
- Joined: Fri Sep 19, 2003 6:28 pm
- Location: Burgos, Spain
- x 2
- Contact:
-
- Gnoll
- Posts: 696
- Joined: Sun Feb 20, 2005 5:28 am
- Contact:
-
- Google Summer of Code Student
- Posts: 78
- Joined: Tue Mar 29, 2005 3:35 pm
- Location: USA
- sinbad
- OGRE Retired Team Member
- Posts: 19269
- Joined: Sun Oct 06, 2002 11:19 pm
- Location: Guernsey, Channel Islands
- x 66
- Contact:
-
- Gnoll
- Posts: 696
- Joined: Sun Feb 20, 2005 5:28 am
- Contact:
I had figured to get the corners of the billboard in screen coordinates to calculate width and height. This figuring area is simply width X height.lodi wrote:Why would you use an occlusion query on a billboard? You can just run the vertices through the current projection matrix and then do a simple formula to get the area in normalised screen coordinates (which you can easily change to # of pixels, or leave it as a ratio of total screen area, which is probably what you wanted in the first place.)
Man that sounds so easy. Is there a working example of this somewhere?
I'll post this in the wiki as soon as I figure it out...
-
- Greenskin
- Posts: 103
- Joined: Sat Jul 24, 2004 7:06 pm
Well as buddy pointed out, I forgot about the case when part of the billboard is occluded by something. But you can still use that kind of idea for lod purposes etc.
The billboard is already orthogonal to the camera, so you don't even need to transform the vertices, you can just get a height and width vector and transform those. Multiply first by the inverse of the camera's view matrix and then the cameras projcection matrix. Normalize w, then height * height of the window * width * width of the window and you have your approximate pixel count. Probably more useful to just use height*width since that'll give you the percentage used (of the whole screen, regardless of resolution)
The billboard is already orthogonal to the camera, so you don't even need to transform the vertices, you can just get a height and width vector and transform those. Multiply first by the inverse of the camera's view matrix and then the cameras projcection matrix. Normalize w, then height * height of the window * width * width of the window and you have your approximate pixel count. Probably more useful to just use height*width since that'll give you the percentage used (of the whole screen, regardless of resolution)
-
- Gnoll
- Posts: 696
- Joined: Sun Feb 20, 2005 5:28 am
- Contact:
This is not the most efficient code but it seems to be working. I'll refine in the morning.
ToScreenCoordinates
Sample code
ToScreenCoordinates
Code: Select all
inline Ogre::Vector2 ToScreenCoordinates(Ogre::Camera *_camera, const Ogre::Vector3 &_position)
{
Ogre::Vector3 hcsPosition = _camera->getProjectionMatrix() * _camera->getViewMatrix() * _position;
return Ogre::Vector2(0.5 - hcsPosition.x * 0.5f, hcsPosition.y * 0.5f + 0.5);
}
Code: Select all
// Get the pixel count
unsigned int pixelCount = m_RenderableOcclusionPair->GetPixelCount();
// Get the render window
Ogre::RenderWindow* renderWindow = Game::GetSingleton()->GetWindow();
assert (renderWindow);
// Get the Camera Scene Node
Ogre::Camera* camera = GetCamera();
assert (camera);
// Approximate area
float halfWidth = m_BillboardWidth*0.5f;
float halfHeight = m_BillboardHeight*0.5f;
Ogre::Vector3 pos = m_OcclusionTestSceneNode->getPosition();
Ogre::Vector3 nX = camera->getOrientation().xAxis().normalisedCopy();
Ogre::Vector3 nY = camera->getOrientation().yAxis().normalisedCopy();
Ogre::Vector2 topLeft = ToScreenCoordinates(camera, pos + nX*(-halfWidth) + nY*halfHeight);
Ogre::Vector2 topRight = ToScreenCoordinates(camera, pos + nX*halfWidth + nY*halfHeight);
Ogre::Vector2 bottomLeft = ToScreenCoordinates(camera, pos + nX*(-halfWidth) + nY*(-halfHeight));
Ogre::Vector2 bottomRight = ToScreenCoordinates(camera, pos + nX*halfWidth + nY*(-halfHeight));
float aX = std::min(0.0f, std::min(topLeft.x, std::min(topRight.x, std::min(bottomLeft.x, bottomRight.x))));
float aY = std::min(0.0f, std::min(topLeft.y, std::min(topRight.y, std::min(bottomLeft.y, bottomRight.y))));
float bX = std::max(1.0f, std::max(topLeft.x, std::max(topRight.x, std::max(bottomLeft.x, bottomRight.x))));
float bY = std::min(1.0f, std::max(topLeft.y, std::max(topRight.y, std::max(bottomLeft.y, bottomRight.y))));
float width = (bX - aX) * renderWindow->getWidth();
float height = (bY - aY) * renderWindow->getHeight();
float area = width*height;
if (area)
{
float ratio = pixelCount/area;
}
-
- Kobold
- Posts: 27
- Joined: Mon Dec 11, 2006 4:38 am
One way to approximate the area would be to use the Camera::projectSphere() method.
This is nice because it returns the bounds of a square in screen coordinate so you can basically replace all your code with a single call. I will try this tonight.
Mat
Code: Select all
bool Ogre::Camera::projectSphere ( const Sphere & sphere,
Real * left,
Real * top,
Real * right,
Real * bottom
) const [virtual]
Mat