class MyRenderer(Renderer):
def __init__(self, svbrdf, mesh, camera, size):
super().__init__(size, 0, 500, camera, show=True)
self.renderables = [Renderable(material, {
'a_position': vertex_positions,
'a_normal': vertex_normals,
'a_tangent': vertex_tangents,
'a_bitangent': vertex_bitangents,
'a_uv': vertex_uvs,
}, len(self.lights))]
def update_uniforms(self):
self.program['cam_pos'] = linalg.inv(self.camera.view_mat())[:3, 3]
self.program['u_view_mat'] = self.camera.view_mat().T
self.program['u_model_mat'] = np.eye(4)
self.program['u_perspective_mat'] = self.camera.perspective_mat().T
for i, light in enumerate(self.lights):
self.program['light_position[{}]'.format(i)] = light.position
self.program['light_intensity[{}]'.format(i)] = light.intensity
self.program['light_color[{}]'.format(i)] = light.color
def draw(self):
gloo.clear(color=(1, 1, 1))
for renderable in self.renderables:
self.program = renderable.program
self.update_uniforms()
self.program.draw(gl.GL_TRIANGLES)
That code has AttributeError
('MyRenderer' object has no attribute renderables)
How to solve? please help me.
Related
I have been, with pygame and pyopengl (oh and obviously Python), been trying to make a little tile-based 2D game, but I'm having trouble with the rendering using VBOs and glMultiDrawArray().
The program runs without errors, but I don't see any geometry drawn, so it's just a blank screen.
I've tried using glTranslate to see if maybe the geometry is being drawn, but I can't see it, as well as changing between using GluPerspective() and glOrthro2D(). No luck. I've pored over the code to see where it isn't working, but I have no clue what could be wrong. I'm still struggling to understand OpenGL and VBOs.
Here are the relevant bits of my code:
The Chunk class. Every chunk has its own VBO for vertices and textures (textures are currently unused)
class Chunk():
def __init__(self, position):
self.Position = position
self.VertexVBOId = _get_chunk_id()
self.VertexVBO = glGenBuffers(self.VertexVBOId)
self.TextureVBOId = _get_chunk_id()
self.TextureVBO = glGenBuffers(self.TextureVBOId)
Chunks[str(position)] = self
self.__updateVertexArray()
# glBindBuffer (GL_ARRAY_BUFFER, self.VertexVBO)
#self.__updateVertexArray()
def __getvertices(self):
vertices = []
for x in range(self.Position.x, self.Position.x + 16):
for y in range(self.Position.y, self.Position.y + 16):
pos = Vector2(x, y)
tile = GetTile(pos)
if tile != "air":
vertices.append(x+1)
vertices.append(y)
vertices.append(x+1)
vertices.append(y+1)
vertices.append(x)
vertices.append(y+1)
vertices.append(x)
vertices.append(y)
return vertices
def __updateVertexArray(self): #This will be called when a change is made the the chunk, as well as once initially
print("UPDATING VERTEX ARRAY")
vertices = self.__getvertices()
glBindBuffer (GL_ARRAY_BUFFER, self.VertexVBOId)
glBufferData (GL_ARRAY_BUFFER, len(vertices)*4, (c_float*len(vertices))(*vertices), GL_DYNAMIC_DRAW)
And here is the rendering loop:
def main():
print("Started")
pygame.init()
global displaySize
global SCREENSIZE
global PIXELS_PER_TILE
pygame.display.set_mode(displaySize, DOUBLEBUF|OPENGL)
#gluOrtho2D(-SCREENSIZE[0]/2, SCREENSIZE[0]/2, -SCREENSIZE[1]/2, SCREENSIZE[1]/2)
gluPerspective(180, 2, 0.1, 100)
... some other stuff ...
while True:
#Drawing
glClearColor(0.7, 0.7, 1, 0)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
cameraTranslateX = (camera.Position.x % 1) * PIXELS_PER_TILE
cameraTranslateY = (camera.Position.y % 1) * PIXELS_PER_TILE
#Figure out which chunks to render
botLeft = camera.Position - Vector2(SCREENSIZE[0]/2, SCREENSIZE[1]/2) + Vector2(cameraTranslateX, cameraTranslateY)
topRight = camera.Position + Vector2(SCREENSIZE[0]/2, SCREENSIZE[1]/2) + Vector2(cameraTranslateX, cameraTranslateY)
FirstChunkPos = (botLeft/16).floor()
TotalChunksX = (topRight/16).ceil().x - FirstChunkPos.x
TotalChunksY = (topRight/16).ceil().y - FirstChunkPos.y
for x in range(TotalChunksX):
for y in range(TotalChunksY):
pos = Vector2(x + FirstChunkPos.x, y + FirstChunkPos.y)
chunk = Chunks.get(str(pos))
if not chunk:
chunk = Chunk(pos)
VertexVBO = chunk.VertexVBOId
glBindBuffer (GL_ARRAY_BUFFER, VertexVBO)
glVertexPointer (2, GL_FLOAT, 0, None)
TextureVBO = chunk.TextureVBOId
glMultiDrawArrays (GL_POLYGON, vertexArrayThingy1, vertexArrayThingy2, 255)
# glUnmapBuffer(GL_ARRAY_BUFFER,VertexVBO)
pygame.display.flip ()
The 2nd and 3rd arguments of glMultiDrawArrays are of type const GLint* and const GLsizei*. This function cannot draw from different buffers. There is no glDraw* command that can use multiple vertex buffers for drawing. All vertecx attributes must be in one and the same buffer. glMultiDrawArrays should draw different ranges from the buffer. Suppose you want to draw the following 3 attribute ranges [3:6], [18:27], [30:36]:
first = [3, 18, 30]
count = [3, 9, 6]
glMultiDrawArrays(GL_TRIANGLES, first, count, 3)
If you want to draw multiple lists of indices you have to use glMultiDrawElements and you have to create an array of pointers to arrays of indices:
import ctypes
ia1 = (GLuint * 6)(0, 1, 2, 0, 2, 3)
ia2 = (GLuint * 6)(12, 13, 14, 12, 14, 15)
counts = [6, 6]
indexPtr = (GLvoidp * 2)(ctypes.addressof(ia1), ctypes.addressof(ia2))
glMultiDrawElements(GL_TRIANGLES, counts, GL_UNSIGNED_INT, indexPtr, 2)
I want to make a simple physical game with balls on Python using pygame and Box2D, but when I try to get the speed of the ball using a well-known method, I get this error. What might be the problem?
class Ball:
def __init__(self, x, y, radius, world, color, fric=0.3, maxspeed=20, density=0.01, restitution=0.5):
self.x = x
self.y = y
self.radius = radius
self.fric = fric
self.maxspeed = maxspeed
self.density = density
self.restitution = restitution
self.color = color
#body
self.bodyDef = box2d.b2BodyDef()
self.bodyDef.type = box2d.b2_dynamicBody
self.bodyDef.position = (x, y)
self.body = world.CreateBody(self.bodyDef)
#shape
self.sd = box2d.b2CircleShape()
self.sd.radius = radius
#fixture
self.fd = box2d.b2FixtureDef()
self.fd.shape = self.sd
#phys params
self.fd.density = density
self.fd.friction = fric
self.fd.restitution = restitution
self.body.CreateFixture(self.fd)
player = Ball(width / 3, height / 2, 30, world, (150, 150, 150))
v = player.body.GetLinearVelocity()
The Error:
Traceback (most recent call last):
File "D:\projs\box2d\bonk\main.py", line 60, in <module>
keyIsDown(pygame.key.get_pressed())
File "D:\projs\box2d\bonk\main.py", line 35, in keyIsDomn
v = player.body.GetLinearVelocity()
AttributeError: 'b2Body' Object has no attribute 'GetLinearVelocity'
screenshot of error
It looks like the GetLinearVelocity method is only available in the C library. The Python wrapper just uses linearVelocity:
v = player.body.linearVelocity
For the future, if you want to know what the variable type is and what methods\properties are available, you can use the type and dir functions:
print(type(player.body)) # class name # <class 'Box2D.Box2D.b2Body'>
print(dir(player.body)) # all methods and properties # ['ApplyAngularImpulse', 'ApplyForce',....,'linearVelocity',...]
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])?
I'm a beginner in Python and have a trouble in running a python module in Rhino3D Grasshopper. The code in a Python module is shown as below.
An instance of Agent alone is working well but when I try to dla.update() with Timer in a next python module(which is simply executing dla.update()), I got the message saying that there is something wrong in self.pos = rs.EvaluateCurve(cirCrv, rndNum) and self.curAgent = Agent(self.cirCrv, self.cenPt, self.walkDist).
Is there a way to make this working ?
import rhinoscriptsyntax as rs
import Rhino.Geometry as rg
import ghpythonlib.components as gh
import random as rnd
class Agent :
def __init__(self, cirCrv, cenPt, walkDist):
self.cenPt = cenPt
self.walkDist = walkDist
rndNum = rnd.random()
self.pos = rs.EvaluateCurve(cirCrv, rndNum)
def randWalk(self) :
v = rs.VectorSubtract(rs.AddPoint(0,0,0), self.pos)
v1 = rs.VectorUnitize(v)
v2 = rs.VectorScale(v1, self.walkDist)
v3 = rs.VectorSubtract(self.pos, rs.AddPoint(0,0,0))
v4 = rs.VectorAdd(v3, gh.UnitZ(1))
rotAxis = rs.VectorSubtract(v4, v3)
newV1 = rs.VectorRotate(v2, rnd.uniform(-70, 70), rotAxis)
self.pos = rs.VectorAdd(self.pos, newV1)
def checkDist(self):
dist1 = rs.Distance(self.pos, rs.AddPoint(0,0,0))
return dist1
class dla :
def __init__(self, cirCrv, cenPt, walkDist):
self.Agents = []
self.cirCrv = cirCrv
self.cenPt = cenPt
self.walkDist = walkDist
self.curAgent = Agent(self.cirCrv, self.cenPt, self.walkDist)
self.pos =self.curAgent.pos
def update(self):
if self.curAgent.checkDist() < 1:
self.Agents.append(self.curAgent)
self.curAgent = Agent(self.cirCrv, self.cenPt, self.walkDist)
else:
self.curAgent.randWalk()
a = dla(cirCrv,cenPt,walkDist)
I'm using Python 2.7.6 and Django 1.5.5.
How I can write a line in SimpleDocTemplate?
I'm tryng this:
#login_required
def report(request):
rep = Report(request.user.username + "_cities.pdf")
# Title
rep.add_header("Cities")
line = Line(0, 100, 500, 100)
rep.add(line)
# Body
columns = ("City")
cities = [(p.name) for p in City.objects.all()]
table = Table([columns] + cities, style=GRID_STYLE)
table.hAlign = "LEFT"
table.setStyle([('BACKGROUND', (1, 1), (-2, -2), colors.lightgrey)])
rep.add(table)
rep.build()
return rep.response
The Line() is from reportlab.graphics.shapes import Line.
The class Report is only a wrapper class to SimpleDocTemplate:
class Report:
styles = None
response = None
document = None
elements = []
def __init__(self, report_file_name):
self.styles = styles.getSampleStyleSheet()
self.styles.add(ParagraphStyle(name='Title2',
fontName="Helvetica",
fontSize=12,
leading=14,
spaceBefore=12,
spaceAfter=6,
alignment=TA_CENTER),
alias='title2')
self.response = HttpResponse(mimetype="application/pdf")
self.response["Content-Disposition"] = "attachment; filename=" + report_file_name
self.document = SimpleDocTemplate(self.response, topMargin=5, leftMargin=2, rightMargin=1, bottomMargin=1)
self.document.pagesize = portrait(A4)
return
def add_header(self, header_text):
p = Paragraph(header_text, self.styles['Title2'])
self.elements.append(p)
def add(self, paragraph):
self.elements.append(paragraph)
def build(self):
self.document.build(self.elements)
When I call report function, I receive the error message:
Line instance has no attribute 'getKeepWithNext'
hen I remove/comment the lines with Line(), the error don't ocurre.
You can help me?
How to write that line?
Just adding Line to the list of elements doesn't work: you can only pass Flowables to SimpleDocTemplate.build(). But you can wrap it in a Drawing, which is a Flowable:
d = Drawing(100, 1)
d.add(Line(0, 0, 100, 0))
rep.add(d)