trouble using cameraOnScene1.getScreenPosition(Target) and using on Overlay scene

so this is what my code is producing -

However the Text is not hovering over the target item like I wish

here is the code that grabs data from the mouse over object and pipes it to the camera in a overlay scene


import bge




def main():


    cont = bge.logic.getCurrentController()
    own = cont.owner
    
    scenes = bge.logic.getSceneList()
    
    for scene in scenes:
        if scene.name =="Overlay":
            Overlay=scene
    Cam2 = Overlay.objects['OverlayCam']
    
    MOA = cont.sensors['MouseOverDescription']
    E = cont.sensors['E']
    
    
    if E.positive and MOA.positive:
        if type(MOA.hitObject['Describe']) is str:
            MOA.hitObject['Describe'] = eval(MOA.hitObject['Describe'])
        print(Cam2['Read'])
        if type(Cam2['Read']) is str:
            print('setting')
            Cam2['Read']=MOA.hitObject['Describe']
            Cam2['Target']=MOA.hitObject
            
        else:
            print(Cam2['Read'])    


main()



it works fine

the issue is commented on


import bge
from mathutils import Vector


def main():


    cont = bge.logic.getCurrentController()
    own = cont.owner
    if own['Go']==False:
        if type(own['Read']) is list:
            own['TextBoxList']=[]
            own['TextList']=[]
            index=0
            for part in own['Read']:
                
                added = own.scene.addObject('Text',own,0)
                added.text=""
                added['Tag']=True
                own['TextBoxList'].append([added,len(part),0,part,index])
                own['TextList'].append([added,index])
                added.applyMovement((-len(part)*.25,-index*.25,-15),1)
                index+=1
            own['Go']=True
    else:
        Target = own['Target']
        
        #Target  is object in other scene
        #Trying to place the text over the object in the main scene using screen matrix
        pes = own['Target'].scene.active_camera.getScreenPosition(own['Target'].worldPosition)
        
        
        pos2 = own.scene.active_camera.getScreenVect(pes[0],pes[1])
        
        for text in own['TextList']:
            
            text[0].worldPosition = pos2+(own.scene.active_camera.worldOrientation.col[2]*-15)
            #text is placed at screen vector and then offset based on length of string and index for line breaks
            # also it is pushed out 15 units so it's in front of the camera


            text[0].applyMovement((-len(text[0].text)*.05,-text[1]*.5,0),1)
            
        if len(own['TextBoxList'])>0:           
            current = own['TextBoxList'][0]
            if current[2]<current[1]:
                current[0].text+=current[3][current[2]]
                current[2]+=1
            else:
                own['TextBoxList'].pop(0)
        else:
            if own['Count']<=59:
                own['Count']+=1
            else:    
                for objects in own.scene.objects:
                    if 'Tag' in objects:
                        objects.endObject()
                        
                own['Go']=False   
                own['Count']=0
                own['Read']="Empty"     
                
                    
main()



why is the text not hovering over the Target object?

I hacked around the issue by setting the overlay camera position and rotation to match the main scene camera, and then just used world space to place the text,

I still would like to know what I did wrong on the screen space translation type text placement though :frowning:

good news is I don’t need to at the moment :smiley:

try this one:


import bge

masterScene = bge.logic.getSceneList()[0]
master = masterScene.objects["Cube"]

slave = bge.logic.getCurrentController().owner

masterCamera = master.scene.active_camera
screenPosition = masterCamera.getScreenPosition(master.worldPosition)
                    
slaveCamera = slave.scene.active_camera
screenVectorInSlaveScene = slaveCamera.getScreenVect(*screenPosition)
distanceToCamera = slaveCamera.worldPosition.z / screenVectorInSlaveScene.z
positionRelativeToSlaveCamera = distanceToCamera * screenVectorInSlaveScene 

slave.worldPosition = slaveCamera.worldPosition - positionRelativeToSlaveCamera

To scale the slave you can move the slave camera away from slave scene origin. Alternatively you can set distanceToCamera at a constant value (in your code).




Attachments

ProjectToCamera.blend (480 KB)

It’s problematic to get data from another scene. Things like setting/getting world position can mess up since they rely on different world data.
The ideal situation is to have an object in the main scene do the calculation (get the screen position) and store it as a property, preferably as a simple data like a tuple.
Then your overlay scene object gets the main scene, finds the object which has the stored data and matches the overlay object to that screen position.

An alternative is to save the data as globaldict so you can pass it between scenes.

There is really no big deal with inter-scene data as long as you have a reference coordinate system. In the above situation the references are the cameras of both scenes. To be more specific the screen coordinate on the rendered image.

You “just” need to know hoe to use the API to do the transformation and fill the missing data. Screen coordinates are 2D while object positions are 3D. This means you get a line in 3D space. Any point on that line is a valid matching point.

Btw. You can define other reference coordinate systems. Here is an example of such a system:

and with moving reference system:

1 Like