I have a simple scene with a cube and via Python (Rasterizer.drawLine()) I can draw lines.
I get the start and end point with a Mouse Over sensor and hitPosition.
The problem is, that the drawLine method needs x, y and z coordinates for the start and end point, which means the line goes through the cube if one point is on the cube and the other for example on the left side a bit behind the cube.
I can’t just add any amount to the y-coordinates of the two points, because in perspective view, the start and end wouldn’t be under the cursor anymore.
I used an invisible plane to get two hitPositions that are always in front of the cube, but for another script, I need a Mouse Over sensor on the cube, which was covered then.
It would be nice if drawLine could be 2D, without the ‘depth’ (y-coordinate).
How could I do this?
I hope my explanations are clear, here’s the script:
import GameLogic as GL, Rasterizer as R
R.showMouse(1)
cont = GL.getCurrentController()
own = cont.owner
objs = GL.getCurrentScene().objects
mouse = cont.sensors["MouseOver"]
LMB = cont.sensors["LMB"]
if mouse.positive:
if LMB.getButtonStatus(182) == 1: ##mouse-button just clicked, save the hit Position
own["start"] = mouse.hitPosition
elif LMB.getButtonStatus(182) == 3: ##mouse-button just released, save the hit Position
own["end"] = mouse.hitPosition
if own.has_key("start") and own.has_key("end"):
R.drawLine(own["start"], own["end"], [1.0,0.0,0.0])
## draw red line from start-point to end-point
The idea with the overlay scene is great, thx.
But I don’t get the part with the screen coordinates. I found the method Camera.getScreenPosition(3D-Vector), which turns my xyz-points into “screen coordinates”. But drawLine needs 3 arguments, and setting the y-coordinate to 0 and those screen coordinates as x and z doesn’t give a good result.
However it would be very good, if the start- and endpoint of the line would be relative to the camera (=Screen), instead of a point in the scene (The line should move with the camera).
If you size the invisible plane so that it appears to be the same size as camera view-port then from a maths point of view, it would just be a case of mapping the screen coordinates on to the plane.
If you let the minimum and maximum coordinates of the plane and screen be as follows(minPx,minPz) (maxPx,maxPz)
(minSz,minSz) (maxSx,maxSz)
For simplicity say the minimums are all zero
ThenPx = Sx*(maxPx/maxSx)
andPz = Sz*(maxPz/maxSz)
You already have Py since it is a constant.
I am not sure how this translates to your Blender problem but if you just want to draw a line on a flat plane then that is it.
To get the line to move with the camera, you have the plane as an overlay and draw the line onto the plane in the overlay scene. The only real problem then is passing the coordinates back and forth between the main scene and the overlay scene, and my recent post on “python and dynamic text” essentially solves that
Having said that, don’t forget I consider myself to be a Blender Noob and if I have misunderstood your intent, then you have my apologies.
hmmm… I’ve been thinking a lot about this problem too. I want an target overlay to show up on the overlay, matching the screen position of a real model in game. Same problem.
The above response is a little heavy in math to understand… but it does offer a good solution. Use an imaginary dummy plane, or establish the area covered by your camera in the overlay scene and map the screen co-ordinates to that area. Of course, be aware that if you change veiwport size the dummy size will have to change too.
Of course, be aware that if you change veiwport size the dummy size will have to change too.
Just by co-incidence, I was reading a post, (recent I think?) by Blendezo that mentioned scaling camera view-ports directly and he seemed to say that it can muck up the logic and do horrible things and they should be left at the default size. Which I suppose means that to change the size of the viewing area you should change the position of the camera and that should not affect the relative size of the overlay.
get window height and width can return the size of the wondow, you will only get problems if you hard code the window size in one of your scripts. Use “get” instead.
Create two vectors, one from the camera to the start of the line and one from the camera to the end of the line.
Set the magnitude of those vectors to something small, .5 perhaps.
The endpoints of these new vectors are the start and end-points of the line. In code it could look like:
import GameLogic
from Mathutils import Vector
cam = GameLogic.getCurrentScene().active_camera
p1 = Vector([0,0,0]) # start of line
p2 = Vector([3,6,-3]) # end of line
vec1 = Vector(cam.worldPosition) - p1
vec2 = Vector(cam.worldPosition) - p2
vec1.magnitude = 0.5
vec2.magnitude = 0.5
p3 = vec1 + Vector(cam.worldPosition) # adding the cam's position because position data is not stored in vectors
p4 = vec2 + Vector(cam.worldPosition)
p3 and p4 are the new points for the line to be drawn on.
That might work better. I tried something with an overlay the other day and it seemed to be drawing the line in the standard world space, not the overlay world space…