pythreejs
pythreejs copied to clipboard
Update colors for buffer geometry
I am trying to change the color of the face of a mesh with buffer geometry when it is clicked on, but nothing I've tried seems to have any effect on the display. Here is my code so far, with the on_picked function attempting to change the color of a picked face. Many of my tries are commented out, from trying to exec the three.js methods to set attributes, to modifying the array of the buffer attribute within python, to changing the entire dict of the buffer geometry - all to no avail. Any guidance would be appreciated.
# Create attributes dictionaries
face_attributes=dict(
position = BufferAttribute(np.asarray(vertices1, dtype=np.float32), normalized=False),
index = BufferAttribute(np.asarray(face_indices, dtype=np.uint32).ravel(), normalized=False),
normal = BufferAttribute(np.asarray(resolved_normals, dtype=np.float32)),
color = BufferAttribute(np.asarray(resolved_colors, dtype=np.float32), needsUpdate=True, dynamic=True)
)
point_attributes = dict(
position = BufferAttribute(np.asarray(vertices, dtype=np.float32), normalized=False),
)
edge_attributes=dict(
position = BufferAttribute(np.asarray(vertices2, dtype=np.float32), normalized=False),
index = BufferAttribute(np.asarray(edge_indices, dtype=np.uint32).ravel(), normalized=False),
)
# create buffer geometries
mesh_geom = BufferGeometry(attributes=face_attributes)
points_geom = BufferGeometry(attributes=point_attributes)
edges_geom = BufferGeometry(attributes=edge_attributes)
# create geometry objects
#g = Geometry(vertices=vertices1.tolist(), faces=tuple(face_indices))
faces_obj = Mesh(geometry=mesh_geom, material=face_mat)
points_obj = Points(geometry=points_geom, material=points_mat)
edges_obj = LineSegments(geometry=edges_geom, material=edges_mat)
#add objects to scene
scene.add([faces_obj, points_obj, edges_obj])
click_picker = Picker(controlling=faces_obj, event='dblclick')
renderer = Renderer(camera=camera, scene=scene, controls=[orbit_controls, click_picker],
width=view_width, height=view_height)
def on_picked(change):
faceIndex = change['new']
obj = change['owner'].controlling
obj.geometry.attributes['color'].needsUpdate = True
new_colors = np.array(obj.geometry.attributes['color'].array, dtype=np.float32)
new_colors[faceIndex] = [255, 0.5, 0.5]
# obj.geometry.attributes['color'].array = new_colors
#obj.geometry.exec_three_obj_method('setAttribute', 'color', BufferAttribute(np.asarray(new_colors, dtype=np.float32), needsUpdate=True))
# obj.exec_three_obj_method('updateMatrix')
#obj.geometry.exec_three_obj_method('applyMatrix4', obj.matrix )
#obj.geometry.attributes['color'].exec_three_obj_method('set', new_colors.tolist())
#obj.geometry.attributes['color'] = BufferAttribute(np.asarray(new_colors, dtype=np.float32), needsUpdate=True)
# obj.geometry.attributes['color'].set(new_colors)
#obj.geometry.exec_three_obj_method('setAttribute','color', obj.geometry.attributes['color'])
obj.geometry.attributes['color'].needsUpdate = True
obj.geometry.attributes = dict({key:val for key, val in obj.geometry.attributes.items() if key != 'color'},
color=BufferAttribute(np.asarray(new_colors, dtype=np.float32), needsUpdate=True))
print(obj.geometry.attributes['color'].array[faceIndex])
click_picker.observe(on_picked, names=['faceIndex'])
display(renderer)
This is how I have been setting colors on a Points object. Maybe it helps?
import pythreejs as p3
import numpy as np
N = 1000
geometry = p3.BufferGeometry(
attributes={
'position':
p3.BufferAttribute(array=20.0 * (np.random.random((N, 3)) - 0.5).astype('float32')),
'color':
p3.BufferAttribute(array=np.zeros([N, 3], dtype='float32'))
})
material = p3.PointsMaterial(vertexColors='VertexColors')
points = p3.Points(geometry=geometry, material=material)
width = 800
height = 500
camera = p3.PerspectiveCamera(position=[40.0, 0, 0], aspect=width / height)
scene = p3.Scene(children=[camera, points], background="#f0f0f0")
controls = p3.OrbitControls(controlling=camera)
renderer = p3.Renderer(camera=camera,
scene=scene,
controls=[controls],
width=width,
height=height)
renderer
Initially all the points are black:

Then, by setting the array of the color attribute,
geometry.attributes["color"].array = np.random.random((N, 3)).astype('float32')
I get
