ksharindam
Posts: 29
Joined: Sat Jan 09, 2016 4:16 pm

pi3d - merge shapes of two different colors

Mon Oct 16, 2017 7:27 am

I want to create a project to view ball and stick model using pi3d. I want balls to be grey and sticks white.
but when I merge balls and sticks using MergeShape , balls and sticks become same colored.

Code: Select all

import pi3d
display = pi3d.Display.create()
camera = pi3d.Camera(eye=(0, 0, -8))  # move camera back

ball = pi3d.Sphere()
cylinder = pi3d.Cylinder(height=3, radius=0.2)
cylinder.set_material((1.0,1.0,1.0))   # Set sticks color white

mol = pi3d.MergeShape(name="merge balls and sticks")
mol.add(ball, -2,0,0)
mol.add(ball, 2,0,0)
mol..add(cylinder, 0, 0, 0, rz=90)

while display.loop_running():
    mol.draw()

How can I do that.

PiGraham
Posts: 2679
Joined: Fri Jun 07, 2013 12:37 pm
Location: Waterlooville

Re: pi3d - merge shapes of two different colors

Mon Oct 16, 2017 9:09 am

I don't much about Pi3D but maybe you can apply a texture to the merged shape to colour it. Alternatively keep the parts as separate meshes with their own colours. There is an AddChild function. Would that allow you to add the ball as a child of a stick so that you can move both as a unit?
The Tiger Tank example might be relevant.

User avatar
paddyg
Posts: 2005
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: pi3d - merge shapes of two different colors

Mon Oct 16, 2017 11:26 am

Hi, @PiGraham is right that one way getting different material colours would be to 'trick' it by using a texture, but it's a bit non-standard, see below. I suspect that you might be hoping to have a large number of balls and sticks (as for a molecule model) which means that the simple parent child option is not an option, but a merged parent to a merged child might be.

The benefit of the MergeShape is that it consolidates all the vertex info into one large Buffer so only one draw() with associated slow python transformation matrix generation has to be done for all the different components. However each Buffer object only has one RGB material slot so each MergeShape is one colour.

a) The texture option. Here the UV coordinates for each component are moved so they only sample a part of the texture. This involves hacking into the numpy array of the Buffer object of the Shape so a bit low level
molecule.jpg
molecule.jpg (100.08 KiB) Viewed 229 times
b) Two MergeShapes one a child of the other. This is probably more in line with your original idea.

Code: Select all

import pi3d
display = pi3d.Display.create()
camera = pi3d.Camera(eye=(0, 0, -8))  # move camera back
# 1. Textures
'''
shader = pi3d.Shader('uv_light')
tex = pi3d.Texture('textures/molecule.jpg')
ball = pi3d.Sphere()
ball.buf[0].array_buffer[:,6:8] *= 0.5 # map UV 0 to 0.5 instead of 0 to 1.0
cylinder = pi3d.Cylinder(height=3, radius=0.2)
cylinder.buf[0].array_buffer[:,6:8] = 0.5 + cylinder.buf[0].array_buffer[:,6:8] * 0.5 # map UV 0.5 to 1.0 instead of 0 to 1.0
mol = pi3d.MergeShape(name="merge balls and sticks")
mol.add(ball, -2,0,0)
mol.add(ball, 2,0,0)
mol.add(cylinder, 0, 0, 0, rz=90)
mol.set_draw_details(shader, [tex])
'''
# 2. Materials
ball = pi3d.Sphere()
cylinder = pi3d.Cylinder(height=3, radius=0.2)
balls = pi3d.MergeShape(name="merge balls")
balls.add(ball, -2,0,0)
balls.add(ball, 2,0,0)
balls.set_material((1.0, 1.0, 0.0))
mol = pi3d.MergeShape(name="merge sticks")
mol.add(cylinder, 0, 0, 0, rz=90)
mol.set_material((1.0, 1.0, 1.0))
mol.add_child(balls)

while display.loop_running():
    mol.draw()
    mol.rotateIncY(0.5)
Screenshot from 2017-10-16 12-12-44.jpg
Screenshot from 2017-10-16 12-12-44.jpg (22.15 KiB) Viewed 229 times
Screenshot from 2017-10-16 12-07-04.jpg
Screenshot from 2017-10-16 12-07-04.jpg (52.23 KiB) Viewed 229 times
P.S. I think I will add a demo along the lines of the following, showing a multi material merge shape. (Figuring out the cylinders is rather non-trivial so I've scaled up the atoms!)

Code: Select all

import pi3d
''' ADP-glucose C16H25N5O15P2 from pubchem.ncbi.nlm.nih.gov
 in form of atomic number then x,y,z locations '''
data = [[15, -0.3572, 3.4667, 1.1986], # phosphorus
        [15, -2.6623, 1.6752, 1.5647],
        [8, 3.0375, 1.6867, -0.7958], # oxygen
        [8, -1.7977, -0.8219, -0.8898],
        [8, 3.0649, 2.0131, -3.8274],
        [8, 2.8223, -0.6735, -3.4983],
        [8, 0.9316, 3.2251, 0.2511],
        [8, -2.945, 0.2338, 0.8963],
        [8, -5.6128, -2.2109, -1.6422],
        [8, -3.6312, -4.0059, -0.5918],
        [8, -5.2209, 0.5051, -0.7228],
        [8, -1.1971, 2.0963, 1.0268],
        [8, 0.2199, -2.7404, 0.0502],
        [8, -1.2455, 4.5426, 0.3799],
        [8, -3.6502, 2.6889, 0.7814],
        [8, -0.0588, 3.8423, 2.6206],
        [8, -2.8016, 1.7059, 3.0593],
        [7, 3.4839, -0.6076, -0.3869], # nitrogen
        [7, 4.1899, -2.4453, 0.6593],
        [7, 1.7782, 0.1326, 1.1761],
        [7, 1.6092, -1.3788, 3.0848],
        [7, 2.9886, -3.3212, 3.3116],
        [6, 2.0293, 1.572, -2.9492], # carbon
        [6, 2.3367, 0.1666, -2.4712],
        [6, 2.1037, 2.3788, -1.6567],
        [6, 3.3925, 0.4325, -1.4091],
        [6, -4.5157, -1.7951, -0.8256],
        [6, -3.3273, -2.7146, -1.1141],
        [6, -4.1665, -0.3458, -1.1584],
        [6, -2.0394, -2.1726, -0.4795],
        [6, 0.7655, 2.4714, -0.9372],
        [6, -2.8438, 0.078, -0.5179],
        [6, -0.814, -2.9872, -0.8848],
        [6, 2.7408, -0.7016, 0.7552],
        [6, 4.3393, -1.6774, -0.3998],
        [6, 3.194, -1.8471, 1.3898],
        [6, 2.5901, -2.1771, 2.5989],
        [6, 1.2692, -0.2895, 2.3539],
        [1, 1.0792, 1.6507, -3.4853], # hydrogen
        [1, 1.4367, -0.2875, -2.0386],
        [1, 2.5103, 3.3838, -1.8158],
        [1, 4.3958, 0.5377, -1.8407],
        [1, -4.8518, -1.8892, 0.2135],
        [1, -3.1984, -2.8228, -2.198],
        [1, -4.0919, -0.2444, -2.2487],
        [1, -2.1202, -2.1969, 0.6158],
        [1, 0.0254, 2.9639, -1.5758],
        [1, 0.4013, 1.4726, -0.6824],
        [1, -2.5686, 1.0477, -0.9476],
        [1, -0.4554, -2.7034, -1.8798],
        [1, -1.022, -4.0612, -0.8668],
        [1, 2.862, 2.931, -4.0768],
        [1, 3.0455, -1.5303, -3.0967],
        [1, 5.0439, -1.8453, -1.2029],
        [1, -5.3466, -2.1268, -2.5736],
        [1, -3.712, -3.9276, 0.3741],
        [1, -4.9662, 1.4192, -0.935],
        [1, 0.9902, -3.264, -0.2292],
        [1, 0.4798, 0.3259, 2.7721],
        [1, -3.7445, 3.6079, 1.111],
        [1, -1.5239, 4.3358, -0.5374],
        [1, 3.7202, -3.9185, 2.951],
        [1, 2.5345, -3.5398, 4.188]]
atoms = {1:['hydrogen', 0.5, (1.0, 0.0, 0.0)],
         6:['carbon', 0.8, (0.1, 0.1, 0.1)],
         7:['nitrogen', 0.9, (0.1, 0.9, 1.0)],
         8:['oxygen', 0.9, (1.0, 1.0, 1.0)],
         15:['phosphorus', 1.5, (1.0, 0.0, 1.0)]}

display = pi3d.Display.create()
camera = pi3d.Camera()

ball = pi3d.Sphere(radius=atoms[6][1])
carbon = pi3d.MergeShape(z=15)
for a in data:
  if a[0] == 6:
    carbon.add(ball, a[1], a[2], a[3])
carbon.set_material(atoms[6][2])

for e in atoms:
  if e != 6: # don't do carbon again
    ball = pi3d.Sphere(radius=atoms[e][1])
    elem = pi3d.MergeShape()
    for a in data:
      if a[0] == e:
        elem.add(ball, a[1], a[2], a[3])
    elem.set_material(atoms[e][2])
    carbon.add_child(elem)

while display.loop_running():
    carbon.draw()
    carbon.rotateIncY(0.5)
    carbon.rotateIncZ(0.1)
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

ksharindam
Posts: 29
Joined: Sat Jan 09, 2016 4:16 pm

Re: pi3d - merge shapes of two different colors

Mon Oct 16, 2017 2:15 pm

Thanks to both PiGraham and paddyg.
Special thanks to paddyg for giving this elaborate answer.

Return to “Python”

Who is online

Users browsing this forum: Danilk, Therysin and 15 guests