Odd rendition

27 views
Skip to first unread message

fgra...@gmail.com

unread,
Dec 7, 2017, 12:52:07 PM12/7/17
to VPython-users
I have tried from some time to run the nice Eyeballs program of M. Garth (http://www.glowscript.org/#/user/murray.garth/folder/Public/program/Eyeballs) directly under Python. The program is unmodified from the GlowScript original (except for the required change of the first line).

The program works, but the display provided in both situations is very different (even with VPython 7.2.0), as the attached images testify. The upright ovoid with spherical eyes of the Glowscript rendering becomes a thin biconvex lens with big cigar shaped eyes under Python. I have been unable to find the root of the problem or any remedy for it, although it seems to me related to the advertised interaction between the axis and size properties of 3D objects *compounded* (if I may say so) by the fact that the object itself is a compound.

Regards


GlowScript Eyeballs.jpg
VPython Eyeballs.jpg

Bruce Sherwood

unread,
Dec 7, 2017, 1:27:52 PM12/7/17
to VPython-users
To my great surprise and chagrin, it's GlowScript VPython that's broken; it doesn't link size to axis as it's supposed to do, if the object is a compound. In the eyeball program the axis is set to a value that has a very large magnitude (6.4) by these statements:

    ebRight.axis = target - ebRight.pos
    ebLeft.axis  = target - ebLeft.pos

VPython 7 correctly uses the magnitude of the axis to update the length of the object, hence the very long "eyes".

Needless to say, I need to correct GlowScript VPython (and increment the version number, as fixing the bug may break some existing program).

Thanks very much for the clear report!

Bruce

Bruce Sherwood

unread,
Dec 7, 2017, 3:26:40 PM12/7/17
to VPython-users
The following version will work with 2.6 and the planned 2.7, as well as with VPython 7. The key point is that changing an object's axis is supposed to set obj.size.x to mag(obj.axis), which is useful in most cases but requires extra code in this situation.

def Eyeball():       # create an eyeball with centre at the origin
    eye = sphere( pos = vec( 0, 0, 0), radius = 0.5, color = color.white )
    iris = sphere( pos = vec( 0.25, 0, 0), radius = 0.31, color = vec( 0, 0, 0.6 ))
    pupil = cylinder( pos = vec( 0, 0, 0), axis = vec( 0.57, 0, 0 ), radius = 0.07, color = color.black)
    obj = compound( [eye, iris, pupil] )
    return obj

scene.width = 1024
scene.height = 768

# create a head compound object, with invisible components used as location placeholders
Skull = sphere( pos = vec( 0, 0, 0), size = vec( 4, 5, 4), color = vec( 0.9, 0.75, 0.625 ))
Nose  = cone( pos = vec( 1.8, -0.7, 0 ), radius = 0.5, axis = vec( -0.1, 2.0, 0 ), color = vec( 0.9, 0.75, 0.625 ))
vRightEye = sphere( pos = vec( 1.6, 0, +0.8), radius = 0.31, color = color.gray(0.2), visible=False)                # 'v' for virtual - placeholder only
vLeftEye  = sphere( pos = vec( 1.6, 0, -0.8), radius = 0.31, color = color.gray(0.2), visible=False)
Head  = compound( [Skull, Nose, vRightEye, vLeftEye] )

Head.angle = Head.length*vec(0,0,1)

ebRight = Eyeball()
ebLeft  = Eyeball()

while True:
    rate(10)

    target = scene.mouse.pos
    target.z = 8               # focus on an object that is 4 units in front of the screen
    
    # Move the head slowly towards the mouse. Move one quarter of the distance each step
    oldAxis = norm(Head.axis)
    newAxis = norm(target - Head.pos)
    Head.axis = Head.length*norm((3.0*oldAxis+1.0*newAxis)/4.0)

    # Place the visible eyeballs in the same position as the invisible placeholders
    world_pos = Head.compound_to_world( vRightEye.pos )
    ebRight.pos = world_pos
    world_pos = Head.compound_to_world( vLeftEye.pos )
    ebLeft.pos = world_pos
    
    # Point the eyeballs at the mouse
    ebRight.axis = ebRight.length*norm(target - ebRight.pos)
    ebLeft.axis  = ebLeft.length*norm(target - ebLeft.pos)

fgra...@gmail.com

unread,
Dec 8, 2017, 4:43:49 AM12/8/17
to VPython-users
Thank you, Bruce, for your kindness and celerity. Refactoring the program was very nice on your side. Indeed things now work as expected under VPython 7.

Paco


Bruce Sherwood

unread,
Dec 8, 2017, 10:19:40 AM12/8/17
to VPython-users
Second thoughts, after sleeping on it and discussing the issues with an experienced colleague:

It's now clear to me that it is the documentation that's wrong, not the GlowScript implementation. The current GlowScript VPython behavior, that changing the axis of a compound object doesn't affect size (length), is appropriate for complicated objects such as compound and, moreover, has been true for years.

It is appropriate and convenient that axis should (and does) affect the length of arrow, cylinder, cone, pyramid, and helix objects, all of which have pos at one end of the object. Note that the size of sphere and ring objects, whose pos is at the center, is not affected by changing its axis, and this is also true for curve objects. Probably axis should not affect the length of a box object, whose pos is at the center, but it's too late to change that.

The remaining issue is that at the moment in VPython 7 is that changing the axis of a compound object affects its length, following the current documentation rather than the current GlowScript behavior. Since VPython 7 is quite new, we'll release an update for it that works the same as GlowScript, namely, axis won't affect length for compound objects.

Again, thanks for documenting the incompatibility!

Bruce

Bruce Sherwood

unread,
Dec 8, 2017, 10:35:10 AM12/8/17
to VPython-users
I'm wrong about curve; changing axis does affect size.

Bruce

Bruce Sherwood

unread,
Dec 8, 2017, 11:54:46 AM12/8/17
to VPython-users
I've updated the Help to document that for compound objects changing the axis doesn't affect size. Next I'll fix VPython 7 to obey this rule.

Bruce
Reply all
Reply to author
Forward
0 new messages