Search code examples
pythonvpython

How to fix: This factory function only works once


This function only works once and then not again can someone tell me what I'm doing wrong?

from vpython import *
def create_cube(pos,size,front,back,left,right,bottom,top):
    c = [ pyramid(pos=pos-vector(0.5,0,0),size=size,color=left),
    pyramid(pos=pos+vector(0.5,0,0),size=size,color=right).rotate(angle=radians(180),axis=vector(0,1,0)),
    pyramid(pos=pos+vector(0,0,0.5),size=size,color=front).rotate(angle=radians(90),axis=vector(0,1,0)),
    pyramid(pos=pos-vector(0,0,0.5),size=size,color=back).rotate(angle=radians(270),axis=vector(0,1,0)),
    pyramid(pos=pos-vector(0,0.5,0),size=size,color=bottom).rotate(angle=radians(90),axis=vector(0,0,1)),
    pyramid(pos=pos+vector(0,0.5,0),size=size,color=top).rotate(angle=radians(270),axis=vector(0,0,1)),
    box(pos=pos,size = vector(0.9,0.9,0.9),color=color.black)]
    return compound(c)

topleftfrontcorner = create_cube(vector(-1,1,1),vector(0.5,0.90,0.90),color.red,color.black,color.blue,color.black,color.black,color.yellow)
topmiddlefrontside = create_cube(vector(0,0,0),vector(0.5,0.90,0.90),color.red,color.black,color.black,color.black,color.black,color.yellow)

I expect this function to output a custom 'cube' every time I call it not just once.


Solution

  • You should return c, and use compound on both topleftfrontcorner and topmiddlefrontside:

    from vpython import *
    def create_cube(pos,size,front,back,left,right,bottom,top):
        c = [ pyramid(pos=pos-vector(0.5,0,0),size=size,color=left),
        pyramid(pos=pos+vector(0.5,0,0),size=size,color=right).rotate(angle=radians(180),axis=vector(0,1,0)),
        pyramid(pos=pos+vector(0,0,0.5),size=size,color=front).rotate(angle=radians(90),axis=vector(0,1,0)),
        pyramid(pos=pos-vector(0,0,0.5),size=size,color=back).rotate(angle=radians(270),axis=vector(0,1,0)),
        pyramid(pos=pos-vector(0,0.5,0),size=size,color=bottom).rotate(angle=radians(90),axis=vector(0,0,1)),
        pyramid(pos=pos+vector(0,0.5,0),size=size,color=top).rotate(angle=radians(270),axis=vector(0,0,1)),
        box(pos=pos,size = vector(0.9,0.9,0.9),color=color.black)]
        return c
    
    topleftfrontcorner = create_cube(vector(-1,1,1),vector(0.5,0.90,0.90),color.red,color.black,color.blue,color.black,color.black,color.yellow)
    topmiddlefrontside = create_cube(vector(0,0,0),vector(0.5,0.90,0.90),color.red,color.black,color.black,color.black,color.black,color.yellow)
    compound(topleftfrontcorner, topmiddlefrontside)
    

    Doing so gives me: enter image description here

    Maybe someone more familiar with vpython can explain more, but in general there's a difference between creating a cube and rendering a cube. The reason why you don't see two cubes in your snippet is that the program is still rendering the first cube (a blocking operation), and hasn't even evaluated the second function call. You can see that's the case by putting a print("hello!") between the two function calls; "hello!" never gets printed because the program is still busy rendering topleftfrontcorner.

    In the updated code snippet, we construct two cubes, then render them at the same time.