Fix the text scene node placing in viewports. The problem was, that the calculation took the absolute viewport dimension into account, while rendering into the viewport requires the screenwidth to be taken. Hence, the text was usually misplaced. The collision method can still be used for this mixed mode calculation (get screen coordinate during viewport rendering, use it for full screen rendering), but requires an additional parameter.

Software drivers don't support 2d rendering into viewports, so they still fail to properly position text (or other 2d things) into a viewport.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3489 dfc29bdd-3216-0410-991c-e03cc46cb475
master
hybrid 2010-12-07 15:22:58 +00:00
parent eff82803d3
commit 014272f2c1
15 changed files with 128 additions and 10 deletions

View File

@ -93,6 +93,10 @@ namespace scene
into 2d. into 2d.
\param camera: Camera to be used. If null, the currently active \param camera: Camera to be used. If null, the currently active
camera is used. camera is used.
\param useViewPort: Calculate screen coordinates relative to
the current view port. Please note that unless the driver does
not take care of the view port, it is usually best to get the
result in absolute screen coordinates (flag=false).
\return 2d screen coordinates which a object in the 3d world \return 2d screen coordinates which a object in the 3d world
would have if it would be rendered to the screen. If the 3d would have if it would be rendered to the screen. If the 3d
position is behind the camera, it is set to (-1000,-1000). In position is behind the camera, it is set to (-1000,-1000). In
@ -100,7 +104,7 @@ namespace scene
method for drawing a decorator over a 3d object, it will be method for drawing a decorator over a 3d object, it will be
clipped by the screen borders. */ clipped by the screen borders. */
virtual core::position2d<s32> getScreenCoordinatesFrom3DPosition( virtual core::position2d<s32> getScreenCoordinatesFrom3DPosition(
const core::vector3df& pos, ICameraSceneNode* camera=0) = 0; const core::vector3df& pos, ICameraSceneNode* camera=0, bool useViewPort=false) = 0;
//! Gets the scene node, which is currently visible under the given screencoordinates, viewed from the currently active camera. //! Gets the scene node, which is currently visible under the given screencoordinates, viewed from the currently active camera.
/** The collision tests are done using a bounding box for each /** The collision tests are done using a bounding box for each

View File

@ -874,7 +874,7 @@ core::line3d<f32> CSceneCollisionManager::getRayFromScreenCoordinates(
//! Calculates 2d screen position from a 3d position. //! Calculates 2d screen position from a 3d position.
core::position2d<s32> CSceneCollisionManager::getScreenCoordinatesFrom3DPosition( core::position2d<s32> CSceneCollisionManager::getScreenCoordinatesFrom3DPosition(
const core::vector3df & pos3d, ICameraSceneNode* camera) const core::vector3df & pos3d, ICameraSceneNode* camera, bool useViewPort)
{ {
if (!SceneManager || !Driver) if (!SceneManager || !Driver)
return core::position2d<s32>(-1000,-1000); return core::position2d<s32>(-1000,-1000);
@ -885,8 +885,11 @@ core::position2d<s32> CSceneCollisionManager::getScreenCoordinatesFrom3DPosition
if (!camera) if (!camera)
return core::position2d<s32>(-1000,-1000); return core::position2d<s32>(-1000,-1000);
const core::rect<s32>& viewPort = Driver->getViewPort(); core::dimension2d<u32> dim;
core::dimension2d<u32> dim(viewPort.getWidth(), viewPort.getHeight()); if (useViewPort)
dim.set(Driver->getViewPort().getWidth(), Driver->getViewPort().getHeight());
else
dim=(Driver->getScreenSize());
dim.Width /= 2; dim.Width /= 2;
dim.Height /= 2; dim.Height /= 2;
@ -905,7 +908,7 @@ core::position2d<s32> CSceneCollisionManager::getScreenCoordinatesFrom3DPosition
core::reciprocal(transformedPos[3]); core::reciprocal(transformedPos[3]);
return core::position2d<s32>( return core::position2d<s32>(
core::round32(dim.Width * transformedPos[0] * zDiv) + dim.Width, dim.Width + core::round32(dim.Width * (transformedPos[0] * zDiv)),
dim.Height - core::round32(dim.Height * (transformedPos[1] * zDiv))); dim.Height - core::round32(dim.Height * (transformedPos[1] * zDiv)));
} }

View File

@ -67,7 +67,7 @@ namespace scene
//! Calculates 2d screen position from a 3d position. //! Calculates 2d screen position from a 3d position.
virtual core::position2d<s32> getScreenCoordinatesFrom3DPosition( virtual core::position2d<s32> getScreenCoordinatesFrom3DPosition(
const core::vector3df & pos, ICameraSceneNode* camera=0); const core::vector3df & pos, ICameraSceneNode* camera=0, bool useViewPort=false);
//! Gets the scene node and nearest collision point for a ray based on //! Gets the scene node and nearest collision point for a ray based on
//! the nodes' id bitmasks, bounding boxes and triangle selectors. //! the nodes' id bitmasks, bounding boxes and triangle selectors.

View File

@ -783,7 +783,6 @@ void CBurningVideoDriver::setViewPort(const core::rect<s32>& area)
Transformation [ ETS_CLIPSCALE ].buildNDCToDCMatrix ( ViewPort, 1 ); Transformation [ ETS_CLIPSCALE ].buildNDCToDCMatrix ( ViewPort, 1 );
if (CurrentShader) if (CurrentShader)
CurrentShader->setRenderTarget(RenderTargetSurface, ViewPort); CurrentShader->setRenderTarget(RenderTargetSurface, ViewPort);
} }
@ -2225,9 +2224,24 @@ void CBurningVideoDriver::draw2DImage(const video::ITexture* texture, const core
return; return;
} }
#if 0
// 2d methods don't use viewPort
core::position2di dest = destPos;
core::recti clip=ViewPort;
if (ViewPort.getSize().Width != ScreenSize.Width)
{
dest.X=ViewPort.UpperLeftCorner.X+core::round32(destPos.X*ViewPort.getWidth()/(f32)ScreenSize.Width);
dest.Y=ViewPort.UpperLeftCorner.Y+core::round32(destPos.Y*ViewPort.getHeight()/(f32)ScreenSize.Height);
if (clipRect)
{
clip.constrainTo(*clipRect);
}
clipRect = &clip;
}
#endif
if (useAlphaChannelOfTexture) if (useAlphaChannelOfTexture)
((CSoftwareTexture2*)texture)->getImage()->copyToWithAlpha( ((CSoftwareTexture2*)texture)->getImage()->copyToWithAlpha(
BackBuffer, destPos, sourceRect, color, clipRect); BackBuffer, destPos, sourceRect, color, clipRect);
else else
((CSoftwareTexture2*)texture)->getImage()->copyTo( ((CSoftwareTexture2*)texture)->getImage()->copyTo(
BackBuffer, destPos, sourceRect, clipRect); BackBuffer, destPos, sourceRect, clipRect);

View File

@ -90,7 +90,6 @@ int main(int argumentCount, char * arguments[])
TEST(b3dAnimation); TEST(b3dAnimation);
TEST(burningsVideo); TEST(burningsVideo);
TEST(cursorSetVisible); TEST(cursorSetVisible);
TEST(drawRectOutline);
TEST(flyCircleAnimator); TEST(flyCircleAnimator);
TEST(md2Animation); TEST(md2Animation);
TEST(testGeometryCreator); TEST(testGeometryCreator);
@ -100,6 +99,7 @@ int main(int argumentCount, char * arguments[])
// all driver checks // all driver checks
TEST(videoDriver); TEST(videoDriver);
TEST(drawPixel); TEST(drawPixel);
TEST(drawRectOutline);
TEST(guiDisabledMenu); TEST(guiDisabledMenu);
TEST(makeColorKeyTexture); TEST(makeColorKeyTexture);
TEST(renderTargetTexture); TEST(renderTargetTexture);
@ -110,7 +110,7 @@ int main(int argumentCount, char * arguments[])
TEST(draw2DImage); TEST(draw2DImage);
TEST(lights); TEST(lights);
TEST(twodmaterial); TEST(twodmaterial);
// TEST(viewPort); TEST(viewPort);
TEST(mrt); TEST(mrt);
// TODO: Needs to be fixed first. // TODO: Needs to be fixed first.
// TEST(projectionMatrix); // TEST(projectionMatrix);

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -81,6 +81,7 @@
<Unit filename="transparentMaterials.cpp" /> <Unit filename="transparentMaterials.cpp" />
<Unit filename="vectorPositionDimension2d.cpp" /> <Unit filename="vectorPositionDimension2d.cpp" />
<Unit filename="videoDriver.cpp" /> <Unit filename="videoDriver.cpp" />
<Unit filename="viewPort.cpp" />
<Unit filename="writeImageToFile.cpp" /> <Unit filename="writeImageToFile.cpp" />
<Unit filename="zipReader.cpp" /> <Unit filename="zipReader.cpp" />
<Extensions> <Extensions>

View File

@ -141,6 +141,7 @@
<ClCompile Include="transparentMaterials.cpp" /> <ClCompile Include="transparentMaterials.cpp" />
<ClCompile Include="vectorPositionDimension2d.cpp" /> <ClCompile Include="vectorPositionDimension2d.cpp" />
<ClCompile Include="videoDriver.cpp" /> <ClCompile Include="videoDriver.cpp" />
<ClCompile Include="viewPort.cpp" />
<ClCompile Include="writeImageToFile.cpp" /> <ClCompile Include="writeImageToFile.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -340,6 +340,10 @@
RelativePath=".\videoDriver.cpp" RelativePath=".\videoDriver.cpp"
> >
</File> </File>
<File
RelativePath=".\viewPort.cpp"
>
</File>
<File <File
RelativePath=".\writeImageToFile.cpp" RelativePath=".\writeImageToFile.cpp"
> >

View File

@ -411,6 +411,10 @@
RelativePath=".\videoDriver.cpp" RelativePath=".\videoDriver.cpp"
> >
</File> </File>
<File
RelativePath=".\viewPort.cpp"
>
</File>
<File <File
RelativePath=".\writeImageToFile.cpp" RelativePath=".\writeImageToFile.cpp"
> >

View File

@ -35,6 +35,8 @@ static bool renderAndLoad(video::E_DRIVER_TYPE driverType)
bool result = takeScreenshotAndCompareAgainstReference(driver, "-textureRenderStates.png", 100); bool result = takeScreenshotAndCompareAgainstReference(driver, "-textureRenderStates.png", 100);
device->closeDevice();
device->run();
device->drop(); device->drop();
return result; return result;
@ -81,6 +83,8 @@ static bool renderAndRemove(video::E_DRIVER_TYPE driverType)
smgr->drawAll(); smgr->drawAll();
driver->endScene(); driver->endScene();
device->closeDevice();
device->run();
device->drop(); device->drop();
return true; return true;
@ -129,6 +133,8 @@ static bool testTextureMatrixInMixedScenes(video::E_DRIVER_TYPE driverType)
bool result = takeScreenshotAndCompareAgainstReference(driver, "-textureMatrixInMixedScenes.png", 99.8f); bool result = takeScreenshotAndCompareAgainstReference(driver, "-textureMatrixInMixedScenes.png", 99.8f);
device->closeDevice();
device->run();
device->drop(); device->drop();
return result; return result;

81
tests/viewPort.cpp Normal file
View File

@ -0,0 +1,81 @@
// Copyright (C) 2008-2009 Colin MacDonald
// No rights reserved: this software is in the public domain.
#include "testUtils.h"
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
//! Tests view ports and text rendering.
/** The result should be as follows: We have three times the same image, a billboard with a cube and the text in front.
They are replicated three times, one centered in the screen without viewport, one in the upper left (qurter screen) and
one on the right (half screen). The latter is stretched due to the changed aspect ratio.
The two viewport scenes get the texture drawn over the center as well, using draw2dimage. This should mark the proper
image position with the top left corner of the texture.
Finally, each scene has a checkbox drawn at the left side, vertically centered. This will show whether GUI elements adhere
to viewports as well. */
static bool viewPortText(E_DRIVER_TYPE driverType)
{
IrrlichtDevice *device = createDevice( driverType, dimension2d<u32>(160, 120), 32);
if (!device)
return true; // Treat a failure to create a driver as benign; this saves a lot of #ifdefs
IVideoDriver* driver = device->getVideoDriver();
ISceneManager * smgr = device->getSceneManager();
IGUIEnvironment* env = smgr->getGUIEnvironment();
env->addCheckBox(true, core::recti(10,60,28,82));
IBillboardSceneNode * bnode = smgr->addBillboardSceneNode(0,dimension2d<f32>(32,32),core::vector3df(0,0,10));
bnode->setMaterialFlag(video::EMF_LIGHTING, false);
bnode->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
bnode->setMaterialTexture(0, driver->getTexture("../media/fire.bmp"));
smgr->addTextSceneNode(device->getGUIEnvironment()->getBuiltInFont(), L"TEST", video::SColor(255,255,255,255), 0);
smgr->addCubeSceneNode();
smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0));
driver->beginScene(true, true, SColor(255,100,101,140));
smgr->drawAll();
env->drawAll();
driver->setViewPort(rect<s32>(0,0,160/2,120/2));
smgr->drawAll();
env->drawAll();
driver->draw2DImage(driver->getTexture("../media/fire.bmp"), core::vector2di(160/2,120/2));
driver->setViewPort(rect<s32>(160/2,0,160,120));
smgr->drawAll();
env->drawAll();
driver->draw2DImage(driver->getTexture("../media/fire.bmp"), core::vector2di(160/2,120/2));
driver->endScene();
bool result = takeScreenshotAndCompareAgainstReference(driver, "-viewPortText.png", 99.8f);
device->drop();
return result;
}
bool viewPort(void)
{
bool passed = true;
logTestString("Check OpenGL driver\n");
passed &= viewPortText(EDT_OPENGL);
// TODO: software driver and burnings don't use view port for
// 2d rendering, so result is pretty wrong.
logTestString("Check Software driver\n");
passed &= viewPortText(EDT_SOFTWARE);
logTestString("Check Burning's Video driver\n");
passed &= viewPortText(EDT_BURNINGSVIDEO);
logTestString("Check Direct3D9 driver\n");
passed &= viewPortText(EDT_DIRECT3D9);
logTestString("Check Direct3D8 driver\n");
passed &= viewPortText(EDT_DIRECT3D8);
return passed;
}