0
$\begingroup$

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!

$\endgroup$
  • $\begingroup$ Why does it need to be python-free? It's impossible without python. $\endgroup$ – palkonimo Jan 12 '17 at 20:24
  • $\begingroup$ Because I'd rather not take the time to learn how to use python with the Blender game engine. Too busy. $\endgroup$ – Flightking14 Jan 12 '17 at 20:49
  • $\begingroup$ You won't need to know python if somebody posts an answer explaining step by step how to get a script getting you what you need to work. And by the way, is it possible not to have what you want to see on another layer or I'm another scene but rather in the same scene on the same layers, just a place the player can't reach and see without the portal? This would make things a lot easier (I don't know if it would be possible otherwise). $\endgroup$ – palkonimo Jan 12 '17 at 20:59
  • $\begingroup$ That might work. This is the effect I was wanting to achieve in the game engine (WARNING LOUD AUDIO): youtu.be/ol0__bZHcU4?t=3m45s If it's not possible, that's fine. I was just wondering. $\endgroup$ – Flightking14 Jan 12 '17 at 21:08
  • 1
    $\begingroup$ I don't have time to write a full answer now, I'll do it later if nobody else has until then. What you could do is basically just having a second camera seeing what the portal should show. Then you put the camera output as a texture on the portal. It would be a similar technique to the one used to create a minimap in this tutorial youtu.be/HgXAv9csJu0 (still a bit different since the portal wouldn't be in an overlay scene) $\endgroup$ – palkonimo Jan 12 '17 at 21:18
0
$\begingroup$

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.

normal facing

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.

creating the image

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.

UVs

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.

Portal Logic

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.

Camera Logic

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.

Empty Orientation

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:


Scripts:

Portal Script:

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[0]*255,scene.world.backgroundColor[1]*255,scene.world.backgroundColor[2]*255, 255)

map_png.source = source

def main():

    map_png.refresh(True)

Camera Script:

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()[0] + pi/2, own.localOrientation.to_euler()[1], own.localOrientation.to_euler()[2]]
$\endgroup$
  • $\begingroup$ Wow this is a very thorough answer. Thank you so much! (sorry for the late reply, I've been busy with college) $\endgroup$ – Flightking14 Jan 24 '17 at 2:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.