Math for RTT Portals [Solved]

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
init512
Posts: 18
Joined: Mon Mar 26, 2007 6:08 pm
Contact:

Math for RTT Portals [Solved]

Post by init512 »

Hello all,
I really love all the work done on Irrlicht, and the great community support I have experienced so far. I do, however, have a math problem dealing with portals, as seen in Valve's Portal. I have been thinking about a game with several additional types of portals (Time, Quantum, Scale), and I tried to get some basic portals working with RTT. I have my rendering set up OK, and it would not be too hard to write code to transport objects between portals. My setup involves two flat surfaces on which I draw a texture captured from a camera at the centre of the opposite portal. I simply can't figure out how to set the target of portal2.camera based on the angle between player's camera and portal1.centre (and vice versa of course). I thought of creating a line3df between player's camera and portal1.centre, and then using the angle and length of that line to determine the target of portal2.camera, but I can't figure out how to manipulate the line3df class in this way. Here is my source code (messy), and some images as well. Any help or alternate methods of implementing portals would be greatly appreciated. :D

Cheers,
Marc

Code: Select all

/* Project: Strange Attraction (portals)
   Author: Marc Burns (2008)

   Parts taken from Irrlicht examples, and
   the Irrlicht forum. Those who wrote said
   parts deserve credit for them.
*/
#include <irrlicht.h>
#include <iostream>
#include "CollisionSystem.h"

using namespace irr;
using namespace std;

int main()
{
	IrrlichtDevice *device =
		createDevice(video::EDT_OPENGL, core::dimension2d<s32>(800, 600), 16, false,true);

	if (device == 0)
		return 1; // could not create selected driver.

	video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();

	driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);
	device->getFileSystem()->addZipFileArchive("./data/TestMapScene.zip");

	device->getCursorControl()->setVisible(false);

	/*I'm about to load a simple testing scene from TestMapScene.zip. It contains a lightmapped
      room with a few pillars and a pool.*/
	smgr->loadScene("sa1.irr");

    //This mesh is to be used as the surface of portals
    scene::IAnimatedMesh* portalmesh = smgr->addHillPlaneMesh("portal",
		core::dimension2d<f32>(30,20),
		core::dimension2d<u32>(8,8), 0, 0,
		core::dimension2d<f32>(0,0),
		core::dimension2d<f32>(1,1));

	if (!(driver->queryFeature(video::EVDF_RENDER_TO_TARGET))) {
	    cout << "FAIL: No RTT for Portals!\n";
        device->drop();
        return 1;
	}

    //Create RTT textures for portals
    video::ITexture* portalrt1 = driver->createRenderTargetTexture(core::dimension2d<s32>(512,512));
    video::ITexture* portalrt2 = driver->createRenderTargetTexture(core::dimension2d<s32>(512,512));

    /*Create nodes for portals, where the mesh is a flat plane of 250x160 units.
      This mesh is textured with the RTT output from the camera positioned at the
      center of the other portal. A transparent texture is drawn on top of the RTT texture
      to create portal effects.*/

    scene::IAnimatedMeshSceneNode* portalnode1 = smgr->addAnimatedMeshSceneNode(portalmesh);
    scene::ICameraSceneNode* portalcamera1 = smgr->addCameraSceneNode();
    portalcamera1->setPosition(core::vector3df(80,120,3));
    portalcamera1->setTarget(core::vector3df(-903,108,831));
    portalnode1->setPosition(core::vector3df(0,120,0));
    portalnode1->setRotation(core::vector3df(90,0,90));
    //portalnode1->setMaterialType(video::EMT_REFLECTION_2_LAYER);
    //portalnode1->setMaterialTexture(0, driver->getTexture("./data/portalstatic.png"));
    portalnode1->setMaterialTexture(0, portalrt1);
    portalnode1->setMaterialFlag(video::EMF_LIGHTING,false);

    scene::IAnimatedMeshSceneNode* portalnode2 = smgr->addAnimatedMeshSceneNode(portalmesh);
    scene::ICameraSceneNode* portalcamera2 = smgr->addCameraSceneNode();
    portalcamera2->setPosition(core::vector3df(240,120,3));
    portalcamera2->setTarget(core::vector3df(-903,108,831));
    portalnode2->setPosition(core::vector3df(240,120,0));
    portalnode2->setRotation(core::vector3df(90,0,90));
    //portalnode2->setMaterialType(video::EMT_REFLECTION_2_LAYER);
    //portalnode2->setMaterialTexture(0, driver->getTexture("./data/portalstatic.png"));
    portalnode2->setMaterialTexture(0, portalrt2);
    portalnode2->setMaterialFlag(video::EMF_LIGHTING,false);

    /*CS_ functions are a simple interface to Irrlicht's built-in collision system. Triangle selectors are
      assigned to each mesh scene node in the scene. They are then added to a meta selector if within
      20 units of the camera.*/

	//Build collision system:
	CS_assignTriangleSelectors(smgr, device->getFileSystem());
    // add a user controlled camera
    scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0, 100.0f, 300.0f, -1, 0, 0, true);
    // Position the Camera
    camera->setPosition(core::vector3df(-50,80,0));
    // Rotate the Camera
    camera->setRotation(core::vector3df(0,90,0));
    //Put the Meta Triangle Selector
    scene::IMetaTriangleSelector* meta = smgr->createMetaTriangleSelector();
    // Node "meta" animation for the Camera
    scene::ISceneNodeAnimator* anim =
    smgr->createCollisionResponseAnimator(meta, camera, core::vector3df(30,50,30), core::vector3df(0,-1,0), core::vector3df(0,50,0));
    // Assign the node anim to the camera
    camera->addAnimator(anim);
    anim->drop();
    meta->drop();

    /*For a pool. Taken from Irrlicht's Special Effects example.*/

    scene::IAnimatedMesh* mesh = smgr->addHillPlaneMesh("pool",
		core::dimension2d<f32>(20,20),
		core::dimension2d<u32>(65,65), 0, 0,
		core::dimension2d<f32>(0,0),
		core::dimension2d<f32>(10,10));

	scene::ISceneNode* node = smgr->addWaterSurfaceSceneNode(mesh->getMesh(0), 3.0f, 300.0f, 30.0f);
	node->setPosition(core::vector3df(-175,-120,-3117));

	node->setMaterialTexture(0, driver->getTexture("./data/submerged.jpg"));
	node->setMaterialTexture(1, driver->getTexture("./data/water.jpg"));

	node->setMaterialType(video::EMT_REFLECTION_2_LAYER);
	node->setMaterialFlag(video::EMF_LIGHTING,false);

	int lastFPS = -1;

    bool whichPortal = false;
	while(device->run())
	if (device->isWindowActive())
	{
		driver->beginScene(true, true, 0);

        /*Portal rendering alternates between portals to make gameplay smoother.
          I hope to internalize all of this into a class soon.*/
        if(whichPortal) {
            driver->setRenderTarget(portalrt1, true, true, 0);
            //--------> Here is where I would have some code to calculate the target of portalcamera2, which is drawn on portalnode1
            smgr->setActiveCamera(portalcamera2);
            smgr->drawAll();
        } else {
            driver->setRenderTarget(portalrt2, true, true, 0);
            smgr->setActiveCamera(portalcamera1);
            smgr->drawAll();
        }

        whichPortal = !whichPortal;
        driver->setRenderTarget(0);
        smgr->setActiveCamera(camera);
		smgr->drawAll();

		driver->endScene();

		int fps = driver->getFPS();

		if (lastFPS != fps)
		{
		  core::stringw str = L"RTT Portals example - Irrlicht Engine [";
		  str += driver->getName();
		  str += "] FPS:";
		  str += fps;
		  str += " Pos: ";
		  str += camera->getPosition().X;
		  str += ", ";
          str += camera->getPosition().Y;
		  str += ", ";
		  str += camera->getPosition().Z;
		  str += ", ";

		  device->setWindowCaption(str.c_str());
		  lastFPS = fps;
		}

		//Update collision:
		meta->removeAllTriangleSelectors();
        core::aabbox3df box(-10.f, -10.f, -10.f, 10.f, 10.f, 10.f);
        camera->getAbsoluteTransformation().transformBoxEx(box);
        // put all selectors into meta selector if they intersect the bounding box
        CS_gatherTriangleSelectors(smgr, meta, box);
	}

	device->drop();

	return 0;
}
Image
A little diagram I drew.

Thank you in advance!
Last edited by init512 on Fri Feb 01, 2008 7:28 pm, edited 1 time in total.
FuzzYspo0N
Posts: 914
Joined: Fri Aug 03, 2007 12:43 pm
Location: South Africa
Contact:

Post by FuzzYspo0N »

fomr what i can think up, use a rotation matrix frm the player camera, and set the camera2 to that rotation matrix. For example,

when i look at the portal from point a :

a

Portal

The portal camera shud be facing the EXACT same direction, just looking at another room for example.
so you rotate camera 2 = camera 1 and then u should (in my head in theory) have the right view isnt it?

Oh and, why recreate ideas??? prey, portal, so many games with this idea :) there is an incredible portal example on the newton forums too, using physics portals, its really impressive
init512
Posts: 18
Joined: Mon Mar 26, 2007 6:08 pm
Contact:

Definitly right...

Post by init512 »

Thanks for the tip. I just took a look at the Newton forums, and I must say that the portal project there is amazing. I've been trying to use RTT and Irrlicht's physics, however I now realize that it would be much more effective to use a real physics engine, and to use the stencil buffer for portals (both of which I know nothing about). I would like to develop this into a game at some time in the future, but it appears I have a long road of learning ahead. Oh well, off to learn of physics and OpenGL and proper 3D mathematics.

Thanks,
Marc
FuzzYspo0N
Posts: 914
Joined: Fri Aug 03, 2007 12:43 pm
Location: South Africa
Contact:

Post by FuzzYspo0N »

No problem!

The misconception that making games is easy should always be learnt, not told. i can tell you its hard, but you gotta try for yourself to know.

If it were that easy to make awesome, "current-gen" games, that are made by teams of over a hundred people, the world would be a better place. But its not easy, and people spend a long time researching methods for these kinda things, you are lucky to have people who have information for you, so you CAN learn.

Dont get discouraged though, it is possible to make anything you strive for, if you set realistic deadlines for learning.

I hope you get to a place where you feel empowered and not feeling like its too hard. It takes hard work, understand that from the beginning and you should be fine
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

I did a portal implementation in irrlicht last year (search the project forum for 'curse of the pharoah') which was inspired in turn by someone else's (better) attempt (blizportals, linked from my curse thread i think).

So.. others have tried and to be honest i pretty much failed really as i didn't get the maths working right. I was young and naive and didn't have much understanding of the topic. Now though i understand it a lot better and would be able to achieve it i reckon so i can probably give some advice.

What Fuzzy says sounds pretty much right to me. I think that's how i had mine set up at one point but it didn't really look quite right... the portal looked flat as if it was in 2D so you couldn't see through the portal in 3D... so i guess i had something wrong there... But anyway, Fuzzy should be right i think.
Image Image Image
FuzzYspo0N
Posts: 914
Joined: Fri Aug 03, 2007 12:43 pm
Location: South Africa
Contact:

Post by FuzzYspo0N »

Yea im guessing though, i messed around with it, but i got a simlar effect to a billboard, it looks 2d. then i tried rotation and it looked much much better, and i wasnt using rotation matrix. the rotation matrix is the exact and correct rotation matrix so its not warped or off perspective...
init512
Posts: 18
Joined: Mon Mar 26, 2007 6:08 pm
Contact:

Thanks

Post by init512 »

Thanks for the great advice. I think I'll start reading through the Newton documentation and tutorials, and also look for info on 3D rendering techniques. I suppose it will be a while before I can put any of my ideas into code, but I'm willing to learn all that is required.

Thanks again,
Marc
Post Reply