I am needing a python-free way to make a layer or scene ONLY visible through a certain object. I want to make like a portal effect where you look through an object into another layer or scene. If anyone knows how to do this, please let me know! I would very much appreciate it!
General idea of making a portal: you have a camera that sees what the portal should show. Then the output of the camera is rendered to the other portal as a texture.
Without python this is not possible though.
So here's a python way to do it (who would have thought? ;) ):
First we create the portal:
You can use whatever mesh you want but a plane mesh is probably the best. Name it something fitting, e.g. "portal". Make sure that when the object isn't rotated (=> rotation of 0,0,0) the object's normal(s) is/are facing towards the -Y-axis.
Next create a new image in the UV/image editor. Make sure that the aspect ratio of the image is the same as the one of your camera. E.g. if your resolution is 1920*1080 the image's resolution could also be 1920*1080.
Then select the portal, create a material and make it shadeless. Head over to the texture tab and create a texture. Assign the created image to it and unwrap the portal (U in edit mode). Set the texture's source to Generated and its mapping coordinates to UV. If the portal's dimensions aren't the same as the image's you should also move the UVs to the image's center.
Last thing left for the portal is the logic. Add an Always Sensor and a Python Controller. Activate the sensor's true level triggering. Now the controller: Choose Module instead of Script and type
portal.main into the text field. Add a new text data block in the text editor and paste in the portal script from below. Name it
portal.py. Then add two string game properties. Name one
camera and the other one
image. The value of the second one is the name of the image you created. We'll fill the other one later.
Now we take care of the camera. So just add one. Again, choose a name that makes sense like "portalCam". You can put this name in the camera property we created moments ago.
Now the logic. Create a new script and paste the camera script in it. Name it something meaningful like
portalCam.py. Add an Always Sensor and a Python Controller and activate true level triggering. Instead of choosing a module just choose the script that was just added. Create three string game properties, the first named
camera, the second named
portal and the third named
reference. Put the name of your player's camera in the first property, the name of the portal in the second one.
The third property's value is the name of a reference object. It's the object the camera is referring to when calculating its position, so it's like another portal. The portal we created will look from the point of view of this reference object. You can use whatever you want, a plane (=> another portal) or just an empty would be fine. Add it and put its name in the
reference property of the portal camera. All that is left to do is positioning and rotating it. The object's local Y-axis is the direction the camera will be looking in. To check the local transformation just hit ⎇ AltSpace and select local.
And now you're done! The portal shows the output of the camera which moves relative to the player camera's movement.
Here's an example .blend:
from bge import logic, texture scene = logic.getCurrentScene() cont = logic.getCurrentController() own = cont.owner portalCam = scene.objects[own["camera"]] matID = texture.materialID(own, "IM" + own["image"]) map_png = texture.Texture(own, matID) source = texture.ImageRender(scene, portalCam) source.background = (scene.world.backgroundColor*255,scene.world.backgroundColor*255,scene.world.backgroundColor*255, 255) map_png.source = source def main(): map_png.refresh(True)
from bge import logic from mathutils import Vector, Euler, Matrix from math import pi #getting all the objects own = logic.getCurrentController().owner scene = logic.getCurrentScene() cam = scene.objects[own["camera"]] portal = scene.objects[own["portal"]] empty = scene.objects[own["reference"]] #calculating the position of the portal camera rotmat = empty.worldOrientation*portal.worldOrientation.inverted()*Matrix.Scale(-1, 3, portal.worldOrientation*Vector((1, 0, 0))) diff = cam.worldPosition-portal.worldPosition diff = rotmat*diff own.worldPosition = empty.worldPosition+diff own.worldOrientation = empty.worldOrientation own.localOrientation = [own.localOrientation.to_euler() + pi/2, own.localOrientation.to_euler(), own.localOrientation.to_euler()]