Linux OpenGL code fails, works on Mac & Windows - python

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

Related

How to solve Newton's Gravity equations when both bodies are moving

I am struggling to numerically solve Newton's equation for gravity using scipy.integrate.solve_ivp. I can get the coding working when one of the bodies is assumed stationary. However as shown in the picture when I use the code below where I am trying to account for the force of the sun on Jupiter and that of Jupiter on the sun, the suns orbit is not correct. It doesn't seem to wobble but instead just heads off away from the COM.
G = 6.67408e-11
msun = 1988500e24
m_jupiter = 1898.13e24
x_pos_j = 2.939022030646856E+00*au
y_pos_j = -4.169544536356319E+00*au
z_pos_j = -4.843813063988785E-02*au
x_vel_j = 6.083727195546033E-03*v_factor
y_vel_j = 4.708328571996785E-03*v_factor
z_vel_j = -1.556609498459863E-04*v_factor
def f_grav(t, y):
x1, x2, x3, v1, v2, v3 = y
# x1_star, x2_star, x3_star = x_other
dydt = [v1,
v2,
v3,
-(x1-x1_star)*G*m/((x1-x1_star)**2+(x2-x2_star)**2+(x3-x3_star)**2)**(3/2),
-(x2-x2_star)*G*m/((x1-x1_star)**2+(x2-x2_star)**2+(x3-x3_star)**2)**(3/2),
-(x3-x3_star)*G*m/((x1-x1_star)**2+(x2-x2_star)**2+(x3-x3_star)**2)**(3/2)]
return dydt
x_jupiter = np.array([x_pos_j, y_pos_j, z_pos_j])
x_sun = np.array([0, 0, 0])
v_sun = np.array([0, 0, 0])
tStart = 0e0
t_End = 20*year
dt = t_End/3000
# minstep = dt/100
domain = (tStart, dt)
temp_end = dt
x1_star, x2_star, x3_star = [0, 0, 0]
init_j = [x_pos_j, y_pos_j, z_pos_j, x_vel_j, y_vel_j, z_vel_j]
init_sun = [20, -20, 20, 15, -15, 0]
while tStart < t_End:
m=msun
ans_j = solve_ivp(fun=f_grav, t_span=domain, y0=init_j)
x1_star, x2_star, x3_star = ans_j['y'][0:3, -1]
v1_star, v2_star, v3_star = ans_j['y'][3:6, -1]
x_jupiter = np.vstack((x_jupiter, (ans_j['y'][0:3, -1])))
init_j = [x1_star, x2_star, x3_star, v1_star, v2_star, v3_star]
# print(init_j[0:3])
m=m_jupiter
ans_sun = solve_ivp(fun=f_grav, t_span=domain, y0=init_sun)
x1_star, x2_star, x3_star = ans_sun['y'][0:3, -1]
v1_star, v2_star, v3_star = ans_sun['y'][3:6, -1]
v_sun = np.vstack((v_sun, (ans_sun['y'][3:6, -1])))
x_sun = np.vstack((x_sun, (ans_sun['y'][0:3, -1])))
init_sun = [x1_star, x2_star, x3_star, v1_star, v2_star, v3_star]
tStart += dt
temp_end = tStart + dt
domain = (tStart,temp_end)
plt.plot(x_jupiter[:,0], x_jupiter[:,1])
plt.plot(x_sun[:,0], x_sun[:,1])
plt.show()
In the code at any given moment to solve the equation I assume that the other star is stationary but only for dt, which I don't think should effect the results. Is this why my plots are wrong and if so how can I better solve the equation when both bodies are moving. The orbit of Jupiter (blue on right image) looks more less correct but not that of the sun (on both images and is orange).

Achieve Rotation in openAI Gym about another anchor

We start building an Enviroment, based on cartpole-v0. We are trying to achieve a similar behaviour of our pole, so it doesn't rotate in the centerpoint, but at the Bottom. We are using set_rotation function from gym.classic_control.rendering. But there is no opportunity to set an anchorpoint.
We tried to translate the filledPolygon before rotation in different directions, but the anchorpoint remains in centerpoint.
import math
import gym
from gym import spaces, logger
from gym.utils import seeding
import numpy as np
from os import path
class THT_Env(gym.Env):
'''
I shorten the code to the render. The other parts of the code is working fine.
'''
def render(self, mode='human'):
screen_width = 600
screen_height = 600
lead_width = 6 #Lead diameter = 0.6mm
lead_length = 103 #Lead lenght ca. 10.3 mm
lead_spacing = 50 #Lead spacing 5 mm
body_height = 80 #Body height 8 mm
body_width = 65 #Body width 6.5 mm
pcb_thickness = 16 #1.6 mm
#pcb_hole_diameter = 9 #0.9mm
pcb_side = 270.5
pcb_middle = 41
if self.viewer is None:
from gym.envs.classic_control import rendering
self.viewer = rendering.Viewer(screen_width, screen_height)
# Initialize Body
fname = path.join(path.dirname(__file__), "assets/WYO_1nM.png")
body = rendering.Image(fname,body_width, body_height)
self.bodytrans = rendering.Transform()
body.add_attr(self.bodytrans)
self.viewer.add_geom(body)
# Initialize Lead 1
l, r, t, b = -lead_width/2, lead_width/2, lead_length/2, -lead_length/2
lead_1 = rendering.FilledPolygon([(l,b),(l,t),(r,t),(r,b)])
lead_1.set_color(.4, .4, .4)
self.lead_1_trans = rendering.Transform(translation=(lead_spacing/2, (-lead_length-body_height)/2))
lead_1.add_attr(self.lead_1_trans)
lead_1.add_attr(self.bodytrans)
self.viewer.add_geom(lead_1)
lead_2 = rendering.FilledPolygon([(l,b),(l,t),(r,t),(r,b)])
lead_2.set_color(.4, .4, .4)
#self.lead_2_trans = rendering.Transform(translation=(-lead_spacing/2, (-lead_length-body_height)/2))
self.lead_2_trans = rendering.Transform(translation=(0, (-lead_length-body_height)/2),rotation=np.pi/2)
lead_2.add_attr(self.lead_2_trans)
lead_2.add_attr(self.bodytrans)
self.viewer.add_geom(lead_2)
l, r, t, b = -pcb_side/2, pcb_side/2, pcb_thickness/2, -pcb_thickness/2
pcb_1 = rendering.FilledPolygon([(l,b),(l,t),(r,t),(r,b)])
pcb_1.set_color(.0, .42, .0)
self.pcb_1_trans = rendering.Transform(translation=(0+pcb_side/2, 110))
pcb_1.add_attr(self.pcb_1_trans)
self.viewer.add_geom(pcb_1)
pcb_2 = rendering.FilledPolygon([(l,b),(l,t),(r,t),(r,b)])
pcb_2.set_color(.0, .42, .0)
self.pcb_2_trans = rendering.Transform(translation=(screen_width-pcb_side/2, 110))
pcb_2.add_attr(self.pcb_2_trans)
self.viewer.add_geom(pcb_2)
l, r, t, b = -pcb_middle/2, pcb_middle/2, pcb_thickness/2, -pcb_thickness/2
self.pcb_mid = rendering.FilledPolygon([(l,b),(l,t),(r,t),(r,b)])
self.pcb_mid.set_color(.0, .42, .0)
self.pcb_mid_trans = rendering.Transform(translation=(screen_width/2, 110))
self.pcb_mid.add_attr(self.pcb_mid_trans)
self.viewer.add_geom(self.pcb_mid)
if self.state is None: return None
x = self.state
body_x = x[0]+screen_width/2
body_y = x[1]+screen_height/2+200
self.bodytrans.set_translation(body_x, body_y)
#self.lead_1_trans.set_translation(0,-lead_length/2)
#self.lead_1_trans.set_rotation(np.pi/2)
return self.viewer.render(return_rgb_array= mode == 'rgb_array')
def close(self):
if self.viewer:
self.viewer.close()
self.viewer = None
The rotation on the right image results in the circumstance the the pole(lead) is no longer connected to the body. What I expect is that the Anchor lies in the lower part of the body.
We were thinking the wrong wayfrom start of. Before we tryed to work with gym we build something with pyglet and learned that pyglet change anchor of images. When building our own gym we centered our leads and thought that we also could change the anchors. After a short pause I realized that the pole of cartpole is centred on the bottom with l,r,t,b.
So the simple solution in our situation was to change this line
l, r, t, b = -lead_width/2, lead_width/2, lead_length/2, -lead_length/2
into this line
l, r, t, b = -lead_width/2, lead_width/2, 0, -lead_length
So the result of this:
Anchor points of gyms pollygons are controlled by vertexes.

Python 2.7 strange behaviour of getPixel function with gtk

I have a problem with my pixel_at function in my code. Here are all necessary code snippets.
Here is my Helper module:
import gtk.gdk
def pixel_at(x, y):
gtk.gdk
rw = gtk.gdk.get_default_root_window()
pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, 1, 1)
pixbuf = pixbuf.get_from_drawable(rw, rw.get_colormap(), x, y, 0, 0, 1, 1)
return tuple(pixbuf.pixel_array[0, 0])
Here is the Controller class for initilaizing:
import Sensors as sensor
import Scanner as sc
import pyautogui
import time
class GameController(object):
COLOR_DINOSAUR = (83, 83, 83)
def __init__(self):
self.offset = (230, 270) #hardcoded Offset
self.width = 600 # hardcoded but alwways the same
# Stores points (jumps)
self.points = 0
#Listeners
self.onGameEnd = None
self.onGameStart = None
self.onSensorData = None
#Game State
self.gameState = 'OVER'
self.sensor = sensor.Sensors()
self.Scanner = sc.Scanner()
Here is my main function:
import pyautogui
import Helper
import GameController as GC
def main():
print Helper.pixel_at(25, 5)
Controller = GC.GameController()
# Just test values for this function
Controller.Scanner.scanUntil([75, 124],
(-2, 0),
(83, 83, 83),
75 / 2)
Here is the code for the Scanner:
import pyautogui
import Helper
def scanUntil(self, start, step, matchColor, iterLimit):
iterations = 0
current = self.makeInBounds(start)
if step[X] == 0 and step[Y] == 0:
return None
while not self.isOutOfBound(current):
color = Helper.pixel_at(current[X], current[Y])
# to slow color = pyautogui.pixel(current[X], current[Y])
if color == matchColor: # Tuple comparison
return current
current[X] += step[X]
current[Y] += step[Y]
iterations += 1
if iterations > iterLimit:
return None
return None
This line color = Helper.pixel_at(current[X], current[Y]) in the Scanner throws the error: Fatal IO error 0 (Success) on X server :0. But the print Helper.pixel_at(25, 5)call in main() returns me the correct RGB tuple.
The error is thrown at pixbuf = pixbuf.get_from_drawable(rw, rw.get_colormap(), x, y, 0, 0, 1, 1) in the pixel_at(x,y) so I think it has something to do with this.
From the documentation at http://www.pygtk.org/pygtk2reference/class-gdkpixbuf.html#method-gdkpixbuf--get-from-drawable I got this clue: In other words, copies image data from a server-side drawable to a client-side RGB(A) buffer.
But I donĀ“t understand this server-side and client side and why is it working in my first print call but not for color = Helper.pixel_at(current[X], current[Y])?

Rendering scipy.spatial.SphericalVoronoi Output

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

glDrawPixels and numpy problems

I'm trying to visualize mandelbrot set using numpy and OpenGL. However I have problems in drawing code, that is glDrawPixels.
When I draw using glDrawPixels I get something black and all messed up, but when using slower method of glBegin & glEnd I get the correct result. Code:
#!/usr/bin/env python3
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from pylab import *
from numpy import *
from time import clock
w,h = 80,60
eps = 2
max_iter = 30
def draw():
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
t = clock()
print("Being calculation")
x = linspace(-1.5, 0.5, w)
y = linspace(-1,1,h)
a, b = meshgrid(x,y)
M = (a + 1j*b).T
Alive = ones((w,h), dtype=bool)
C = M.copy()
esc = max_iter * ones((w,h), dtype=int32)
for k in range(max_iter):
M[Alive] = square(M[Alive]) + C[Alive]
esc[logical_and(Alive, abs(M) > eps)] = k
Alive = abs(M) < eps
colorsMap = array([0x8B0000FF, 0xA52A2AFF, 0xB22222FF, 0xDC143CFF, 0xFF0000FF, 0xFF6347FF, 0xFF7F50FF, 0xCD5C5CFF, 0xF08080FF, 0xE9967AFF, 0xFA8072FF, 0xFFA07AFF, 0xFF4500FF, 0xFF8C00FF, 0xFFA500FF, 0xFFD700FF, 0xB8860BFF, 0xDAA520FF, 0xEEE8AAFF, 0xBDB76BFF, 0xF0E68CFF, 0x808000FF, 0xFFFF00FF, 0x9ACD32FF, 0x556B2FFF, 0x6B8E23FF, 0x7CFC00FF, 0x7FFF00FF, 0xADFF2FFF, 0x006400FF, 0x008000FF, 0x228B22FF, 0x00FF00FF, 0x32CD32FF, 0x90EE90FF, 0x98FB98FF, 0x8FBC8FFF, 0x00FA9AFF, 0x00FF7FFF, 0x2E8B57FF, 0x66CDAAFF, 0x3CB371FF, 0x20B2AAFF, 0x2F4F4FFF, 0x008080FF, 0x008B8BFF, 0x00FFFFFF, 0x00FFFFFF, 0xE0FFFFFF, 0x00CED1FF, 0x40E0D0FF, 0x48D1CCFF, 0xAFEEEEFF, 0x7FFFD4FF, 0xB0E0E6FF, 0x5F9EA0FF, 0x4682B4FF, 0x6495EDFF, 0x00BFFFFF, 0x1E90FFFF, 0xADD8E6FF, 0x87CEEBFF, 0x87CEFAFF, 0x191970FF, 0x000080FF, 0x00008BFF, 0x0000CDFF, 0x0000FFFF, 0x4169E1FF, 0x8A2BE2FF, 0x4B0082FF, 0x483D8BFF, 0x6A5ACDFF, 0x7B68EEFF, 0x9370DBFF, 0x8B008BFF, 0x9400D3FF, 0x9932CCFF, 0xBA55D3FF, 0x800080FF, 0xD8BFD8FF, 0xDDA0DDFF, 0xEE82EEFF, 0xFF00FFFF, 0xDA70D6FF, 0xC71585FF, 0xDB7093FF, 0xFF1493FF, 0xFF69B4FF, 0xFFB6C1FF, 0xFFC0CBFF, 0xFAEBD7FF, 0xF5F5DCFF, 0xFFE4C4FF, 0xFFEBCDFF, 0xF5DEB3FF, 0xFFF8DCFF, 0xFFFACDFF, 0xFAFAD2FF, 0xFFFFE0FF, 0x8B4513FF, 0xA0522DFF, 0xD2691EFF, 0xCD853FFF, 0xF4A460FF, 0xDEB887FF, 0xD2B48CFF, 0xBC8F8FFF, 0xFFE4B5FF, 0xFFDEADFF, 0xFFDAB9FF, 0xFFE4E1FF, 0xFFF0F5FF, 0xFAF0E6FF, 0xFDF5E6FF, 0xFFEFD5FF, 0xFFF5EEFF, 0xF5FFFAFF, 0x708090FF, 0x778899FF, 0xB0C4DEFF, 0xE6E6FAFF, 0xFFFAF0FF, 0xF0F8FFFF, 0xF8F8FFFF, 0xF0FFF0FF, 0xFFFFF0FF, 0xF0FFFFFF, 0xFFFAFAFF], dtype=uint32)
cmap = zeros((w,h), dtype=uint32)
for k in range(max_iter):
cmap[esc == k] = colorsMap[k]
print("Finish Calculation: {:.2f}".format(clock() - t))
t = clock()
print("Begin Drawing")
if True: #Change for effect
glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, cmap.data)
else:
#Primite drawing numpy array
def transform(cl):
r = ((cl >> 24) & 0xFF) / 256.0
b = ((cl >> 16) & 0xFF) / 256.0
g = ((cl >> 8) & 0xFF) / 256.0
return (r,b,g)
glBegin(GL_POINTS)
for y in range(0,h):
for x in range(0,w):
glColor3f(*transform(cmap[x,y]))
glVertex2i(x,y)
glEnd()
glFlush()
print("Finish drawing: {:.2f}".format(clock() - t))
def idle():
glutPostRedisplay()
def reshape(width, height):
global w,h
w,h =width, height
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluOrtho2D(0, width, height, 0)
glClearColor( 1., 1., 1., 0.)
glClear( GL_COLOR_BUFFER_BIT )
glPointSize(1.0)
glColor3f(0., 0., 0.)
glutInit(sys.argv)
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB)
glutInitWindowSize(w,h)
glutInitWindowPosition(100,100)
glutCreateWindow("Fraktali")
glutReshapeFunc(reshape)
glutDisplayFunc(draw)
glutMainLoop()
glDrawPixels() expects the data in row-major ("raster scan") order, whereas mine array was in column-major order. Didn't know that was how numpy saved data in memory. This solved the problem:
glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ascontiguousarray(cmap.transpose()).data)
Thanks to user GClements on openGL forum.

Categories

Resources