How to convert the length of a line on the screen to the length of an object.
-
hi,
I tried to have an object display its coordinate axis at a fixed screen space length, but it didn't work properly. Where did I make a mistake with my code?This is a c4d file that displays its coordinate axis using tags.-->
video:
-
Hey @chuanzhen,
Thank you for reaching out to us. I do not really understand what your code is meant to do. The line
length = size/bd.WP_W(pos,True)
makes for example no sense to me, as you are here trying to get the size of a world space unit in screen space units, be that the divisor of a constant you defined. And as the input you use the position of your object, to then later use that value as the size of your axis gizmos.Perspective projections, i.e., functions such as
BaseView.WS
, are non-linear transforms. Other than the linear transforms carried out by Cinema 4D'sMatrix
class, they do not preserve length relations. In less fancy words: When you project the three axis of a coordinate system from world space (where each has the length of 1) into screen space, you will end up with three vectors with three different lengths. I.e., the operation is non-linear, as it does not preserve the length relations between things one feeds into it; before x, y, z were all of the same length, now they are not anymore. Your code ignores this fact when you mix up world and screen space values in a line as suchx = bd.WS(mg * c4d.Vector(length,0,0))
(length
is used as a world space component but has been constructed with screen space values).I think what you want to do here, is draw a 'thing', e.g., an axis gizmo in a size that is independent of the position of the object in world space. You can do two things here:
- Project the 'thing' into screen space and move and normalize it there. One way could be for example to project all vectors into screen space, and then normalize their bounding box, i.e., make the box which encompasses them always the same size. But this would result in a "unsteady" animation, when carried out incorrectly, as the width of the drawing shrinks and grows when the object is rotated around its y-axis (as the x-axis rotates in and out of vision). So, you would have to normalize over the width and height (pick the bigger), and rather then simple normalizing, would have to clamp the bounding box, so that its width and height cannot larger than a value X. This can all get non-trivial quite fast.
- The much easier option is just do project the object from a fixed distance and position, which would allow you that 'fixed size'. But also here perspective distortions can be an issue when you then additionally move the drawing (as I did below). This is why such things are usually done in a parallel projection and not a perspective projection.
The underlying answer is therefore that what you are trying to do, is conceptually impossible, or at least very much non-trivial.
Cheers,
FerdinandResult
-
@ferdinand Thanks for your help.
For the unwanted effect of perspective distortion, I tried projecting a fixed size line onto an object to determine the length of the projected line in the world, and then proceeded to draw it.
-
Hey,
Yes, parallel/orthographic projection is effectively just the dot product. The modelling examples cover point plane projections with a function very similar to yours. There is also c4d.utils.PointLineSegmentDistance but I never use it, as it strikes me as more cumbersome to use than just doing the math yourself.
Cheers,
Ferdinand