Rendering scipy.spatial.SphericalVoronoi Output - python

I am attempting to render the output from SciPy SphericalVoronoi using the THREE.js library. I was hoping it would be relatively straight forward based on the matplotlib example in the scipy docs.
Update 2/18/17:
I didn't originally account for the voronoi regions being quads, so this splits them into triangles now. I did get the unit cube example working; however, scaling up the geometry doesn't seem to be complete.
Python script:
import json
import numpy as np
from scipy.spatial import SphericalVoronoi
# http://stackoverflow.com/questions/27050108/convert-numpy-type-to-python/27050186#27050186
class NumpyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, np.integer):
return int(obj)
elif isinstance(obj, np.floating):
return float(obj)
elif isinstance(obj, np.ndarray):
return obj.tolist()
else:
return super(NumpyEncoder, self).default(obj)
def computeVoronoi( data ):
vertices = np.array( data['vertices'] )
lenVerts = int( vertices.shape[0] / 3 )
vertices = np.reshape( vertices, ( lenVerts, 3 ) )
voronoi = SphericalVoronoi( vertices, data['regularRadius'] )
'''
points = np.array([[0, 0, 1], [0, 0, -1], [1, 0, 0], [0, 1, 0], [0, -1, 0], [-1, 0, 0], ])
voronoi = SphericalVoronoi( points, 1, np.array([0, 0, 0]) )
'''
voronoi.sort_vertices_of_regions()
return voronoi
if __name__ == '__main__':
with open( './map.json' ) as infile:
voronoi = computeVoronoi( json.load( infile ) )
indices = []
for region in voronoi.regions:
# need to split the quad into tris for rendering
i1 = region[0]
i2 = region[1]
i3 = region[2]
i4 = region[3]
indices.append( i1 )
indices.append( i2 )
indices.append( i3 )
indices.append( i3 )
indices.append( i4 )
indices.append( i1 )
with open( './voronoi.json', 'w' ) as outfile:
json.dump( {
'indices': indices,
'colors': np.random.random( (len( voronoi.vertices ),3) ).flatten(),
'vertices': voronoi.vertices.flatten()
}, outfile, cls=NumpyEncoder )
THREE.js script:
var loader = new THREE.FileLoader()
loader.load( 'voronoi.json', function( data ) {
vJson = JSON.parse( data )
var geometry = new THREE.BufferGeometry()
geometry.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( vJson.vertices ), 3 ) )
geometry.addAttribute( 'color', new THREE.BufferAttribute( new Float32Array( vJson.colors ), 3 ) )
geometry.setIndex( new THREE.BufferAttribute( new Uint32Array( vJson.indices ), 1 ) )
var voronoiMesh = new THREE.Mesh(
geometry,
new THREE.MeshBasicMaterial({
color: 0xffffff,
side: THREE.DoubleSide,
vertexColors: THREE.VertexColors,
})
)
scene.add( voronoiMesh )
})
Here's what the render looks like now:
render link

Related

Manim: Is the a nice way to move and scale a bunch of mobjects?

I'm using the manim module in Python to display some decision trees. Fist I want to show Tree_1 as it is in the code below. Then I want it to scale it down and shift it to the left. Next I want Tree_2 to appear where Tree_1 is and them move to the upper right quadrant of the screen. Also the PURE_RED lines should move from tilted (as in Tree_1) to straight (as in Tree_2 in the code below). The same should then happen with Tree_3 just in the bottom right quadrant.
Now I could do it by figuring out all the points and then hardcode it. But I wanted to ask if there is a nicer way. Maybe one where I could define points in a local coordinate system and then I can just scale and move the whole tree.
Also I'm sorry if its is considered common knowledge, but I'm super new to manim.
from manim import *
class Tree_1(Scene):
def construct(self):
line_1 = Line([0,3,0], [-6,0,0])
line_2 = Line([0,3,0], [0,0,0])
line_3 = Line([0,3,0], [6,0,0])
self.play(
Create(line_1),
Create(line_2),
Create(line_3),
)
line_1l = Line([-6, 0, 0], [-7,-3, 0]).set_color(PURE_GREEN)
line_1r = Line([-6, 0, 0], [-5,-3, 0]).set_color(PURE_RED)
line_2l = Line([ 0, 0, 0], [-1,-3, 0]).set_color(PURE_GREEN)
line_2r = Line([ 0, 0, 0], [ 1,-3, 0]).set_color(PURE_RED)
line_3l = Line([ 6, 0, 0], [ 5,-3, 0]).set_color(PURE_GREEN)
line_3r = Line([ 6, 0, 0], [ 7,-3, 0]).set_color(PURE_RED)
self.play(
Create(line_1l),
Create(line_1r),
Create(line_2l),
Create(line_2r),
Create(line_3l),
Create(line_3r),
)
class Tree_2(Scene):
def construct(self):
line_1 = Line([0,3,0], [-6,0,0])
line_2 = Line([0,3,0], [0,0,0])
line_3 = Line([0,3,0], [6,0,0])
self.play(
Create(line_1),
Create(line_2),
Create(line_3),
)
line_4 = Line([-6, 0, 0], [-6,-3, 0]).set_color(PURE_RED)
line_5 = Line([ 0, 0, 0], [-0,-3, 0]).set_color(PURE_RED)
line_6 = Line([ 6, 0, 0], [ 6,-3, 0]).set_color(PURE_RED)
self.play(
Create(line_4),
Create(line_5),
Create(line_6),
)
class Tree_3(Scene):
def construct(self):
line_1 = Line([0,3,0], [-6,0,0])
line_2 = Line([0,3,0], [0,0,0])
line_3 = Line([0,3,0], [6,0,0])
self.play(
Create(line_1),
Create(line_2),
Create(line_3),
)
line_4 = Line([-6, 0, 0], [-6,-3, 0]).set_color(PURE_GREEN)
line_5 = Line([ 0, 0, 0], [-0,-3, 0]).set_color(PURE_GREEN)
line_6 = Line([ 6, 0, 0], [ 6,-3, 0]).set_color(PURE_GREEN)
self.play(
Create(line_4),
Create(line_5),
Create(line_6),
)
Yes there is, add them to a VGroup, here is the docs.

IKPy Problem: TypeError: __init__() missing 1 required positional argument: 'origin_translation'

I am trying to use IKPy Library(v3.3.3) with Python 3.8 to program some demos for my robot arm on the Mujoco platform. However, When I try to do the Kinematic demo, there is something wrong that happened as below.
enter image description here
Here is my project code below:
utils.py
from mujoco_py import MjViewer
import glfw
import numpy as np
import ikpy
from ikpy.chain import Chain
from ikpy.link import OriginLink, URDFLink
open_viewers = [] # a static list to keep track of all viewers
class MjViewerExtended(MjViewer):
""" An extension of mujoco-py's MjViewer. MjViewerExtended does not
terminate all other viewers and the python interpreter when closeing.
"""
def __init__(self, sim):
glfw.init() # make sure glfw is initialized
super().__init__(sim)
open_viewers.append(self)
def close(self):
""" Closes the viewers glfw window. To open a new one, create a new
instance of MjViewerExtended
"""
# MjViewer only calls glfw.terminate() here killing glfw entierly.
if glfw.window_should_close(self.window):
return
try:
glfw.set_window_should_close(self.window, 1)
glfw.destroy_window(self.window)
except Exception:
pass
open_viewers.remove(self)
if len(open_viewers) == 0:
glfw.terminate()
def key_callback(self, window, key, scancode, action, mods):
if action == glfw.RELEASE and key == glfw.KEY_ESCAPE:
self.close()
else:
super().key_callback(window, key, scancode, action, mods)
class Wam4IK(Chain):
""" A basic kinamatic model of the MjWAM4 """
def __init__(self, tool_orientation=None,
tool_translation=None, # x, y, z
base_orientation=None, # x, y, z
base_translation=None):
if base_translation is None:
base_translation = [0, 0, 0.84]
if base_orientation is None:
base_orientation = [0, 0, np.pi / 2]
if tool_translation is None:
tool_translation = [0, 0, 0]
if tool_orientation is None:
tool_orientation = [0, 0, 0]
links = [OriginLink(),
URDFLink(name="wam/links/base",
translation=base_translation, # translation of frame
origin_orientation=base_orientation, # orientation of frame
rotation=[0, 0, 0]
), # joint axis [0, 0, 0] -> no joint
URDFLink(name="wam/links/shoulder_yaw",
translation=[0, 0, 0.16],
origin_orientation=[0, 0, 0],
rotation=[0, 0, 1]
),
URDFLink(name="wam/links/shoulder_pitch",
translation=[0, 0, 0.186],
origin_orientation=[0, 0, 0],
rotation=[1, 0, 0]
),
URDFLink(name="wam/links/shoulder_roll",
translation=[0, 0, 0],
origin_orientation=[0, 0, 0],
rotation=[0, 0, 1]
),
URDFLink(name="wam/links/upper_arm",
translation=[0, -0.045, 0.550],
origin_orientation=[0, 0, 0],
rotation=[1, 0, 0]
),
URDFLink(name="wam/links/tool_base_wo_plate",
translation=[0, 0.045, 0.350],
origin_orientation=[0, 0, 0],
rotation=[0, 0, 0]
),
URDFLink(name="wam/links/tool_base_w_plate",
translation=[0, 0, 0.008],
origin_orientation=[0, 0, 0],
rotation=[0, 0, 0]
),
URDFLink(name="wam/links/tool",
translation=tool_translation,
origin_orientation=tool_orientation,
rotation=[0, 0, 0]
)
]
self.all_joints = [False, False, True, True, True, True, False, False, False]
self.active_joints = list(map(lambda x: x == 1, active_joints))
self.active_links = [False, False, *self.active_joints, False, False, False]
Chain.__init__(self, name='wam4',
active_links_mask=self.active_links,
links=links)
def fk(self, joints, full_kinematics=False):
joints = np.array([0, 0, *joints, 0, 0, 0])
return Chain.forward_kinematics(self, joints, full_kinematics)
def ik(self, target_position=None, target_orientation=None, orientation_mode=None, **kwargs):
full = Chain.inverse_kinematics(self, target_position, target_orientation, orientation_mode, **kwargs)
active = self.joints_from_links(full)
return active
def joints_from_links(self, joints):
return np.compress(self.all_joints, joints, axis=0)
kinematics.py
import numpy as np
from mujoco_robots.utils import Wam4IK
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
# from juggling_wams.envs import SingleArmOneBall
from mujoco_robots.robots import MjWam4
def plot_joints(chain, qs):
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='3d', facecolor="1.0")
for pos in qs:
chain.plot([0, 0] + pos + [0, 0, 0], ax)
plt.xlabel('x')
plt.ylabel('y')
plt.show()
def main():
chain = Wam4IK(base_translation=[0, 0, 0.84],
base_orientation=[0, 0, np.pi / 2])
links = ['wam/links/base',
'wam/links/shoulder_yaw',
'wam/links/shoulder_pitch',
'wam/links/upper_arm',
'wam/links/forearm',
'wam/links/tool_base_wo_plate',
'wam/links/tool_base_w_plate']
x0 = np.array([0, 0, 0.84])
q_test = [[0, 0, 0, 0], [1, 1, 1, 1]]
robot = MjWam4(render=True, g_comp=True)
for q in q_test:
print(f'\n\ntesting for q={q}')
robot.reset(pos=q)
cart = chain.forward_kinematics([0, 0] + q + [0, 0, 0], full_kinematics=True)
for i in range(7):
print(f'\n{links[i][10:]}')
mj_pos = robot.get_body_full_mat(links[i])[:3, 3] - x0
ikpy_pos = cart[i + 1][:3, 3] - x0
print(f'mj: {mj_pos}')
print(f'ikpy: {ikpy_pos}')
print(f'diff: {mj_pos - ikpy_pos}')
plot_joints(chain, q_test)
# inverse kinematics
x_des = [0.15, 0.86, 1.45]
q = chain.active_from_full(chain.inverse_kinematics(x_des))
robot.set_mocap_pos('endeff_des', x_des)
robot.step(des_pos=q, n_steps=5000)
if __name__ == '__main__':
main()
I think there is no problem with my environment setting and other python files. The problem I think should be happened in these two files. If you would like to see other files, I would upload them soon. Thanks!
You made several calls like this:
URDFLink(name="wam/links/shoulder_yaw",
translation=[0, 0, 0.16],
origin_orientation=[0, 0, 0],
rotation=[0, 0, 1]
),
Please be sure to specify the mandatory origin_translation argument.

Customizing a Networkx graph (or Scatter) with Python Plotly

I'm using Plotly's Python interface to generate a network. I've managed to create a network with my desired nodes and edges, and to control the size of the nodes.
I am desperately looking for help on how to do the following:
add node labels
add edge labels according to a list of weights
control the edge line width according to a list of weights
All this without using the "hovering" option, as it has to go in a non-interactive paper. I'd greatly appreciate any help! Plotly's output |
In case this fails, the figure itself |
matrix.csv
This is my code (most is copy-pasted from the Plotly tutorial for Networkx):
import pandas as pd
import plotly.plotly as py
from plotly.graph_objs import *
import networkx as nx
matrix = pd.read_csv("matrix.csv", sep = "\t", index_col = 0, header = 0)
G = nx.DiGraph()
# add nodes:
G.add_nodes_from(matrix.columns)
# add edges:
edge_lst = [(i,j, matrix.loc[i,j])
for i in matrix.index
for j in matrix.columns
if matrix.loc[i,j] != 0]
G.add_weighted_edges_from(edge_lst)
# create node trace:
node_trace = Scatter(x = [], y = [], text = [], mode = 'markers',
marker = Marker(
showscale = True,
colorscale = 'YIGnBu',
reversescale = True,
color = [],
size = [],
colorbar = dict(
thickness = 15,
title = 'Node Connections',
xanchor = 'left',
titleside = 'right'),
line = dict(width = 2)))
# set node positions
pos = nx.spring_layout(G)
for node in G.nodes():
G.node[node]['pos']= pos[node]
for node in G.nodes():
x, y = G.node[node]['pos']
node_trace['x'].append(x)
node_trace['y'].append(y)
# create edge trace:
edge_trace = Scatter(x = [], y = [], text = [],
line = Line(width = [], color = '#888'),
mode = 'lines')
for edge in G.edges():
x0, y0 = G.node[edge[0]]['pos']
x1, y1 = G.node[edge[1]]['pos']
edge_trace['x'] += [x0, x1, None]
edge_trace['y'] += [y0, y1, None]
edge_trace['text'] += str(matrix.loc[edge[0], edge[1]])[:5]
# size nodes by degree
deg_dict = {deg[0]:int(deg[1]) for deg in list(G.degree())}
for node, degree in enumerate(deg_dict):
node_trace['marker']['size'].append(deg_dict[degree] + 20)
fig = Figure(data = Data([edge_trace, node_trace]),
layout = Layout(
title = '<br>AA Substitution Rates',
titlefont = dict(size = 16),
showlegend = True,
margin = dict(b = 20, l = 5, r = 5, t = 40),
annotations = [dict(
text = "sub title text",
showarrow = False,
xref = "paper", yref = "paper",
x = 0.005, y = -0.002)],
xaxis = XAxis(showgrid = False,
zeroline = False,
showticklabels = False),
yaxis = YAxis(showgrid = False,
zeroline = False,
showticklabels = False)))
py.plot(fig, filename = 'networkx')
So
1. The solution to this is relative easy, you create a list with the node ids and you set it in the text attribute of the scatter plot. Then you set the mode as "markers+text" and you're done.
2. This is a little bit more tricky. You have to calculate the middle of each line and create a list of dicts including the line's middle position and weight. Then you add set as the layout's annotation.
3. This is too compicated to be done using plotly IMO. As for now I am calculating the position of each node using networkx spring_layout function. If you'd want to set the width of each line based on its weight you would have to modify the position using a function that takes into account all the markers that each line is attached to.
Bonus I give you the option to color each of the graph's components differently.
Here's a (slightly modified) function I made a while ago that does 1 and 2:
import pandas as pd
import plotly.plotly as py
import plotly.graph_objs as go
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
import networkx as nx
def scatter_plot_2d(G, folderPath, name, savePng = False):
print("Creating scatter plot (2D)...")
Nodes = [comp for comp in nx.connected_components(G)] # Looks for the graph's communities
Edges = G.edges()
edge_weights = nx.get_edge_attributes(G,'weight')
labels = [] # names of the nodes to plot
group = [] # id of the communities
group_cnt = 0
print("Communities | Number of Nodes")
for subgroup in Nodes:
group_cnt += 1
print(" %d | %d" % (group_cnt, len(subgroup)))
for node in subgroup:
labels.append(int(node))
group.append(group_cnt)
labels, group = (list(t) for t in zip(*sorted(zip(labels, group))))
layt = nx.spring_layout(G, dim=2) # Generates the layout of the graph
Xn = [layt[k][0] for k in list(layt.keys())] # x-coordinates of nodes
Yn = [layt[k][1] for k in list(layt.keys())] # y-coordinates
Xe = []
Ye = []
plot_weights = []
for e in Edges:
Xe += [layt[e[0]][0], layt[e[1]][0], None]
Ye += [layt[e[0]][1], layt[e[1]][1], None]
ax = (layt[e[0]][0]+layt[e[1]][0])/2
ay = (layt[e[0]][1]+layt[e[1]][1])/2
plot_weights.append((edge_weights[(e[0], e[1])], ax, ay))
annotations_list =[
dict(
x=plot_weight[1],
y=plot_weight[2],
xref='x',
yref='y',
text=plot_weight[0],
showarrow=True,
arrowhead=7,
ax=plot_weight[1],
ay=plot_weight[2]
)
for plot_weight in plot_weights
]
trace1 = go.Scatter( x=Xe,
y=Ye,
mode='lines',
line=dict(color='rgb(90, 90, 90)', width=1),
hoverinfo='none'
)
trace2 = go.Scatter( x=Xn,
y=Yn,
mode='markers+text',
name='Nodes',
marker=dict(symbol='circle',
size=8,
color=group,
colorscale='Viridis',
line=dict(color='rgb(255,255,255)', width=1)
),
text=labels,
textposition='top center',
hoverinfo='none'
)
xaxis = dict(
backgroundcolor="rgb(200, 200, 230)",
gridcolor="rgb(255, 255, 255)",
showbackground=True,
zerolinecolor="rgb(255, 255, 255)"
)
yaxis = dict(
backgroundcolor="rgb(230, 200,230)",
gridcolor="rgb(255, 255, 255)",
showbackground=True,
zerolinecolor="rgb(255, 255, 255)"
)
layout = go.Layout(
title=name,
width=700,
height=700,
showlegend=False,
plot_bgcolor="rgb(230, 230, 200)",
scene=dict(
xaxis=dict(xaxis),
yaxis=dict(yaxis)
),
margin=dict(
t=100
),
hovermode='closest',
annotations=annotations_list
, )
data = [trace1, trace2]
fig = go.Figure(data=data, layout=layout)
plotDir = folderPath + "/"
print("Plotting..")
if savePng:
plot(fig, filename=plotDir + name + ".html", auto_open=True, image = 'png', image_filename=plotDir + name,
output_type='file', image_width=700, image_height=700, validate=False)
else:
plot(fig, filename=plotDir + name + ".html")
The d3graph library provides the functionalities you want.
pip install d3graph
I downloaded your data and imported it for demonstration:
# Import data
df = pd.read_csv('data.csv', index_col=0)
# Import library
from d3graph import d3graph
# Convert your Pvalues. Note that any edge is set when a value in the matrix is >0. The edge width is however based on this value. A conversion is therefore useful when you work with Pvalues.
df[df.values==0]=1
df = -np.log10(df)
# Increase some distance between edges. Maybe something like this.
df = (np.exp(df)-1)/10
# Make the graph with default settings
d3 = d3graph()
# Make the graph by setting some parameters
d3.graph(df)
# Set edge properties
d3.set_edge_properties(directed=True)
# Set node properties
d3.set_node_properties(color=df.columns.values, size=size, edge_size=10, edge_color='#000000', cmap='Set2')
This will result in an interactive network graph. Two screenshots: one with the default settings and the one with tweaked settings. More examples can be found here.

Linux OpenGL code fails, works on Mac & Windows

I have a fairly complex Python based OpenGL code that runs fine on Windows and Mac, but fails with weird banded-spheres on Linux. Views from two angles:
Here is what the same code plots on a Mac:
The problem is not only with spheres, but this is the easiest thing to show. Does this problem suggest anything to anyone with more experience with OpenGL than I?
Thanks for any hints or suggestions.
Here is some sample code that shows this problem
'''Draws a sphere and axis triplet with openGL; rotates with mouse drag.
This works fine on Windows and Mac, but sphere displays strangely on Linux
'''
import sys
import math
import numpy as np
import numpy.linalg as nl
import wx
import wx.glcanvas
import OpenGL.GL as GL
import OpenGL.GLU as GLU
drawingData = {
'oldxy' : [0, 0],
'Quaternion' : np.array([ 0.11783419, 0.87355958, 0.09141639, 0.4633053 ]),
'linecolors': [(np.array([[0, 0, 0], [1, 0, 0]]), [255, 0, 0]),
(np.array([[0, 0, 0], [0, 1, 0]]), [ 0, 255, 0]),
(np.array([[0, 0, 0], [0, 0, 1]]), [ 0, 0, 255])],
}
def Q2Mat(Q):
''' make rotation matrix from quaternion
'''
QN = Q/np.sqrt(np.sum(np.array(Q)**2))
aa = QN[0]**2
ab = QN[0]*QN[1]
ac = QN[0]*QN[2]
ad = QN[0]*QN[3]
bb = QN[1]**2
bc = QN[1]*QN[2]
bd = QN[1]*QN[3]
cc = QN[2]**2
cd = QN[2]*QN[3]
dd = QN[3]**2
M = [[aa+bb-cc-dd, 2.*(bc-ad), 2.*(ac+bd)],
[2*(ad+bc), aa-bb+cc-dd, 2.*(cd-ab)],
[2*(bd-ac), 2.*(ab+cd), aa-bb-cc+dd]]
return np.array(M)
def prodQVQ(Q,V):
"""compute the quaternion vector rotation qvq-1 = v'
"""
T2 = Q[0]*Q[1]
T3 = Q[0]*Q[2]
T4 = Q[0]*Q[3]
T5 = -Q[1]*Q[1]
T6 = Q[1]*Q[2]
T7 = Q[1]*Q[3]
T8 = -Q[2]*Q[2]
T9 = Q[2]*Q[3]
T10 = -Q[3]*Q[3]
M = np.array([[T8+T10,T6-T4,T3+T7],[T4+T6,T5+T10,T9-T2],[T7-T3,T2+T9,T5+T8]])
VP = 2.*np.inner(V,M)
return VP+V
def invQ(Q):
'''get inverse of quaternion q=r+ai+bj+ck; q* = r-ai-bj-ck
'''
return Q*np.array([1,-1,-1,-1])
def AVdeg2Q(A,V):
''' convert angle (degrees) & vector to quaternion
q=r+ai+bj+ck
'''
sind = lambda x: math.sin(x*math.pi/180.)
cosd = lambda x: math.cos(x*math.pi/180.)
Q = np.zeros(4)
d = nl.norm(np.array(V))
if not A: #== 0.!
A = 360.
if d:
V = V/d
p = A/2.
Q[0] = cosd(p)
Q[1:4] = V*sind(p)
else:
Q[3] = 1.
return Q
def prodQQ(QA,QB):
''' Grassman quaternion product, QA,QB quaternions; q=r+ai+bj+ck
'''
D = np.zeros(4)
D[0] = QA[0]*QB[0]-QA[1]*QB[1]-QA[2]*QB[2]-QA[3]*QB[3]
D[1] = QA[0]*QB[1]+QA[1]*QB[0]+QA[2]*QB[3]-QA[3]*QB[2]
D[2] = QA[0]*QB[2]-QA[1]*QB[3]+QA[2]*QB[0]+QA[3]*QB[1]
D[3] = QA[0]*QB[3]+QA[1]*QB[2]-QA[2]*QB[1]+QA[3]*QB[0]
return D
def RenderUnitVectors(x,y,z):
'Show the axes'
GL.glEnable(GL.GL_COLOR_MATERIAL)
GL.glLineWidth(2)
GL.glEnable(GL.GL_BLEND)
GL.glBlendFunc(GL.GL_SRC_ALPHA,GL.GL_ONE_MINUS_SRC_ALPHA)
GL.glEnable(GL.GL_LINE_SMOOTH)
GL.glPushMatrix()
GL.glTranslate(x,y,z)
GL.glScalef(1,1,1)
GL.glBegin(GL.GL_LINES)
for line,color in drawingData['linecolors']:
GL.glColor3ubv(color)
GL.glVertex3fv(-line[1]/2.)
GL.glVertex3fv(line[1]/2.)
GL.glEnd()
GL.glPopMatrix()
GL.glColor4ubv([0,0,0,0])
GL.glDisable(GL.GL_LINE_SMOOTH)
GL.glDisable(GL.GL_BLEND)
GL.glDisable(GL.GL_COLOR_MATERIAL)
def RenderSphere(x,y,z,radius,color):
'show a sphere'
GL.glMaterialfv(GL.GL_FRONT_AND_BACK,GL.GL_DIFFUSE,color)
GL.glPushMatrix()
GL.glTranslate(x,y,z)
GL.glMultMatrixf(np.eye(4).T)
GLU.gluSphere(GLU.gluNewQuadric(),radius,20,10)
GL.glPopMatrix()
class myGLCanvas(wx.Panel):
def __init__(self, parent, id=-1,dpi=None,**kwargs):
wx.Panel.__init__(self,parent,id=id,**kwargs)
if 'win' in sys.platform: # for Windows (& darwin==Mac) -- already double buffered
attribs = None
else: # Linux
attribs = [wx.glcanvas.WX_GL_DOUBLEBUFFER,]
self.canvas = wx.glcanvas.GLCanvas(self,-1,attribList=attribs,**kwargs)
self.context = wx.glcanvas.GLContext(self.canvas)
self.canvas.SetCurrent(self.context)
sizer=wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.canvas,1,wx.EXPAND)
self.SetSizer(sizer)
self.canvas.Bind(wx.EVT_MOTION, self.OnMouseMove)
self.Draw()
self.Draw()
return
def OnMouseMove(self,event):
if not event.Dragging():
drawingData['oldxy'] = list(event.GetPosition())
return
# Perform a rotation in x-y space
oldxy = drawingData['oldxy']
if not len(oldxy): oldxy = list(event.GetPosition())
dxy = event.GetPosition()-oldxy
drawingData['oldxy'] = list(event.GetPosition())
V = np.array([dxy[1],dxy[0],0.])
A = 0.25*np.sqrt(dxy[0]**2+dxy[1]**2)
if not A: return
# next transform vector back to xtal coordinates via inverse quaternion & make new quaternion
Q = drawingData['Quaternion']
V = prodQVQ(invQ(Q),np.inner(np.eye(3),V))
Q = prodQQ(Q,AVdeg2Q(A,V))
drawingData['Quaternion'] = Q
self.Draw()
def Draw(self):
GL.glClearColor(0.,0.,0.,0.)
GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
GL.glInitNames()
GL.glPushName(0)
GL.glMatrixMode(GL.GL_PROJECTION)
GL.glLoadIdentity()
GL.glViewport(0,0,*self.canvas.GetSize())
GLU.gluPerspective(20.,self.canvas.GetSize()[0]*1./self.canvas.GetSize()[1],7.5,12.5)
GLU.gluLookAt(0,0,10,0,0,0,0,1,0)
# Set Lighting
GL.glEnable(GL.GL_DEPTH_TEST)
GL.glEnable(GL.GL_LIGHTING)
GL.glEnable(GL.GL_LIGHT0)
GL.glLightModeli(GL.GL_LIGHT_MODEL_TWO_SIDE,0)
GL.glLightfv(GL.GL_LIGHT0,GL.GL_AMBIENT,[1,1,1,1])
GL.glLightfv(GL.GL_LIGHT0,GL.GL_DIFFUSE,[1,1,1,1])
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glLoadIdentity()
matRot = Q2Mat(drawingData['Quaternion'])
matRot = np.concatenate((np.concatenate((matRot,[[0],[0],[0]]),axis=1),[[0,0,0,1],]),axis=0)
GL.glMultMatrixf(matRot.T)
GL.glMultMatrixf(np.eye(4).T)
Tx,Ty,Tz = (0.20045985394544949, 0.44135342324377724, 0.40844172594191536)
GL.glTranslate(-Tx,-Ty,-Tz)
RenderUnitVectors(Tx,Ty,Tz)
RenderSphere(0, 0, 0, 0.804, [1., 1., 1.])
self.canvas.SetCurrent(self.context)
self.canvas.SwapBuffers()
class GUI(wx.App):
def OnInit(self):
frame = wx.Frame(None,-1,'ball rendering',wx.DefaultPosition,wx.Size(400,400))
frame.Show()
wx.CallAfter(myGLCanvas,frame,size=wx.Size(400,400)) # wait for frame to be displayed
self.MainLoop()
return True
if __name__ == '__main__':
GUI()
You have to specify the number of the bits for the depth buffer, according to the conditions of your hardware, by setting WX_GL_DEPTH_SIZE. The size of the depth buffer should be 16, 24 or 32.
attribs = [
wx.glcanvas.WX_GL_RGBA,
wx.glcanvas.WX_GL_DOUBLEBUFFER,
wx.glcanvas.WX_GL_DEPTH_SIZE, 16]
See also:
How can I determine the max allowable WX_GL_DEPTH_SIZE for a wx GLCanvas?
OpenGL depth buffer deosn't seem to work in wx.glcanvas?
wx.glcanvas.WX_GL_DEPTH_SIZE
wxGLCanvas

Assign multiple shaders to imported .OBJ files in Maya

I need to import multiple files into Maya and assign multiple materials to each one.
I have the following code in Python:
import maya.cmds as cmds
import glob
def importFile(i):
cmds.file(i, i=True, groupReference=True, groupName="myobj")
def moveFile():
cmds.select("myobj")
cmds.scale(1,1,1, r=True)
cmds.move (0, 14, 0, r=True)
cmds.rotate (-90, 0, 0, r=True)
def materialFile():
cmds.select("myobj")
myMaterial = "blinn1"
cmds.sets( e=True, forceElement= myMaterial + 'SG' )
def renderFile(i):
cmds.setAttr("defaultRenderGlobals.imageFilePrefix", i, type="string")
cmds.render(batch=True)
def deleteFile():
cmds.select("myobj")
cmds.delete()
myglob = glob.glob("/The/path/of/your/Obj_files/*.obj")
for i in myglob:
importFile(i)
moveFile()
materialFile()
renderFile(i)
deleteFile()
With this code I can assign only one shader to the whole piece of geometry.
Is it possible to assign different shaders to the same piece of geometry?
Definitely, you can assign different shaders to the same piece of geometry as well as any accessible shader for multiple 3d models.
import maya.cmds as mat
d = 0
shader_node1 = mat.shadingNode( "anisotropic", asShader = True, n = 'ani' )
shader_node2 = mat.shadingNode( "phong", asShader = True, n = 'pho' )
shader_node3 = mat.shadingNode( "lambert", asShader = True, n = 'lam' )
mat.setAttr( (shader_node1 + '.color'), 1.0, 0.0, 0.0, type = 'double3' )
mat.setAttr( (shader_node2 + '.color'), 0.0, 1.0, 0.0, type = 'double3' )
mat.setAttr( (shader_node2 + '.transparency'), 0.25, 0.25, 0.25, type = 'double3' )
mat.setAttr( (shader_node3 + '.color'), 0.0, 0.0, 1.0, type = 'double3' )
shading_group1 = mat.sets( renderable = True, noSurfaceShader = True, empty = True )
shading_group2 = mat.sets( renderable = True, noSurfaceShader = True, empty = True )
shading_group3 = mat.sets( renderable = True, noSurfaceShader = True, empty = True )
mat.connectAttr( '%s.outColor' %shader_node1, '%s.surfaceShader' %shading_group1 )
mat.connectAttr( '%s.outColor' %shader_node2, '%s.surfaceShader' %shading_group2 )
mat.connectAttr( '%s.outColor' %shader_node3, '%s.surfaceShader' %shading_group3 )
mat.polySphere( radius = 5 )
mat.polySphere( radius = 7 )
mat.polySphere( radius = 3 )
mat.select( 'pSphere1' )
mat.move( 7, 6, 0, r = True )
mat.hyperShade( assign = shader_node1 )
mat.select( 'pSphere2' )
mat.hyperShade( assign = shader_node2 )
mat.select( 'pSphere3' )
mat.move( -7, -2, 0, r = True )
mat.hyperShade( assign = shader_node3 )
d += 1
Also you can access your shaders within an array using random function:
import random as random
myArray = [shader_node1, shader_node2, shader_node3]
for i in myArray :
mat.select( 'pSphere1' )
mat.move( 7, 6, 0, r = True )
mat.hyperShade( assign = myArray[int(random.uniform(0,3))] )
mat.select( 'pSphere2' )
mat.hyperShade( assign = myArray[int(random.uniform(0,3))] )
mat.select( 'pSphere3' )
mat.move( -7, -2, 0, r = True )
mat.hyperShade( assign = myArray[int(random.uniform(0,3))] )

Categories

Resources