Форум сайта python.su
Не пойму, чего я не знаю, и, что надо узнать.
Увлекаюсь 3D. Рендер рисует открывающуюся картинку. В иных случаях за 1-10 секунд.
Не напрягаясь просчётом моделирую симуляцию рендера:
#!/usr/bin/python3 from PyQt4 import QtCore, QtGui from PyQt4.QtGui import * from PyQt4.QtCore import * import random class Render(QWidget): def __init__(self, parent=None): super(Render, self).__init__(parent) self.timer = QBasicTimer() self.pixmap = QPixmap() self.pixmap.load("/home/leonid/blender/textures/green_gradient_rotate.png") self.step = 0; self.timer.start(.000000000000001, self) def paintEvent(self, event): x = random.randint(1, self.pixmap.width()-1) y = random.randint(1, self.pixmap.height()-1) img = self.pixmap.toImage() img.setPixel(x, y,QColor(Qt.white).rgb()) self.pixmap.convertFromImage(img, Qt.AutoColor) painter = QPainter(self) painter.drawPixmap (0, 0, img.width(), img.height(), self.pixmap) def timerEvent(self, event): if event.timerId() == self.timer.timerId(): self.update() else: super(Render, self).timerEvent(event) class RenderWindow(QDialog): def __init__(self, parent=None): super(RenderWindow, self).__init__(parent) render = Render() layout = QVBoxLayout() layout.addWidget(render) self.setLayout(layout) self.setWindowTitle("Render") self.resize(360, 145) if __name__ == '__main__': import sys app = QApplication(sys.argv) win = RenderWindow() win.show(); sys.exit(app.exec_())
Отредактировано leonid_10 (Янв. 31, 2015 14:53:48)
Офлайн
Не такой он и медленный. У меня скорость составила 8000 точек за 10 сек, что при задержке в 1мс вполне нормально.
from PyQt4 import QtCore, QtGui from PyQt4.QtGui import * from PyQt4.QtCore import * import random class Render(QWidget): def __init__(self, parent=None): super(Render, self).__init__(parent) self.timer = QTimer(self) self.connect(self.timer, QtCore.SIGNAL("timeout()"), self.update) self.timer.start(1) self.pixmap = QtGui.QImage("/home/rodegast/0_8e0fc_8f99dbfc_XL.jpg") self.t1 = 0 def paintEvent(self, event): x = random.randint(1, self.pixmap.width()-1) y = random.randint(1, self.pixmap.height()-1) self.pixmap.setPixel(x, y, 0) painter = QPainter(self) painter.drawImage(QtCore.QPoint(0, 0), self.pixmap) self.t1 += 1 print self.t1 class RenderWindow(QDialog): def __init__(self, parent=None): super(RenderWindow, self).__init__(parent) render = Render() layout = QVBoxLayout() layout.addWidget(render) self.setLayout(layout) self.setWindowTitle("Render") self.resize(360, 145) if __name__ == '__main__': import sys app = QApplication(sys.argv) win = RenderWindow() win.show(); sys.exit(app.exec_())
Офлайн
RodegastНет. Это не нормально. Во-первых, скорость не увеличивается с уменьшением задержки.
Не такой он и медленный. У меня скорость составила 8000 точек за 10 сек, что при задержке в 1мс вполне нормально.
Офлайн
Кстати, Ваш код не работает, ибо Python 3:
Traceback (most recent call last):
File “pyprog_timer_qt.py”, line 15, in paintEvent
x = random.randint(1, self.pixmap.width()-1)
File “/usr/lib64/python3.4/random.py”, line 218, in randint
return self.randrange(a, b+1)
File “/usr/lib64/python3.4/random.py”, line 196, in randrange
raise ValueError(“empty range for randrange() (%d,%d, %d)” % (istart, istop, width))
ValueError: empty range for randrange() (1,0, -1)
Офлайн
> Кстати, Ваш код не работает, ибо Python 3:
А он и не должен.
> Во-первых, скорость не увеличивается с уменьшением задержки.
У меня увеличивается.
> Во-вторых, каким образом картинка в 480 000 пикселов открывается за 5 секунд в Java или C++?
Вот видишь какой Python быстрый. В моём примере картинка разрешением 700x800 (560 000 пикселов) отрисовывалась 800 раз в секунду, а на Java / C++ меньшее изображение рисуется аж за 5 секунд.
Отредактировано Rodegast (Янв. 31, 2015 18:42:52)
Офлайн
Rodegast
> Кстати, Ваш код не работает, ибо Python 3:А он и не должен.> Во-первых, скорость не увеличивается с уменьшением задержки.У меня увеличивается.> Во-вторых, каким образом картинка в 480 000 пикселов открывается за 5 секунд в Java или C++?Вот видишь какой Python быстрый. В моём примере картинка разрешением 700x800 (560 000 пикселов) отрисовывалась 800 раз в секунду, а на Java / C++ меньшее изображение рисуется аж за 5 секунд.
normaltest rendering 3D scene time taken 163.617372 ------------------ (program exited with code: 0) Press return to continue
""" Pure Python ray-tracer :) taken directly from http://pastebin.com/f8f5ghjz with modifications another good one alternative at http://www.hxa.name/minilight/ some more equations for getting intersection with other 3d geometries, https://www.cl.cam.ac.uk/teaching/1999/AGraphHCI/SMAG/node2.html#SECTION00023200000000000000 """ #IMPORTS from math import sqrt, pow, pi import time import PIL,PIL.Image #GEOMETRIES class Vector( object ): def __init__(self,x,y,z): self.x = x self.y = y self.z = z def dot(self, b): return self.x*b.x + self.y*b.y + self.z*b.z def cross(self, b): return (self.y*b.z-self.z*b.y, self.z*b.x-self.x*b.z, self.x*b.y-self.y*b.x) def magnitude(self): return sqrt(self.x**2+self.y**2+self.z**2) def normal(self): mag = self.magnitude() return Vector(self.x/mag,self.y/mag,self.z/mag) def __add__(self, b): return Vector(self.x + b.x, self.y+b.y, self.z+b.z) def __sub__(self, b): return Vector(self.x-b.x, self.y-b.y, self.z-b.z) def __mul__(self, b): assert type(b) == float or type(b) == int return Vector(self.x*b, self.y*b, self.z*b) class Sphere( object ): def __init__(self, center, radius, color): self.c = center self.r = radius self.col = color def intersection(self, l): q = l.d.dot(l.o - self.c)**2 - (l.o - self.c).dot(l.o - self.c) + self.r**2 if q < 0: return Intersection( Vector(0,0,0), -1, Vector(0,0,0), self) else: d = -l.d.dot(l.o - self.c) d1 = d - sqrt(q) d2 = d + sqrt(q) if 0 < d1 and ( d1 < d2 or d2 < 0): return Intersection(l.o+l.d*d1, d1, self.normal(l.o+l.d*d1), self) elif 0 < d2 and ( d2 < d1 or d1 < 0): return Intersection(l.o+l.d*d2, d2, self.normal(l.o+l.d*d2), self) else: return Intersection( Vector(0,0,0), -1, Vector(0,0,0), self) def normal(self, b): return (b - self.c).normal() class Cylinder( object ): "just a copy of sphere, needs work. maybe see http://stackoverflow.com/questions/4078401/trying-to-optimize-line-vs-cylinder-intersection" def __init__(self, startpoint, endpoint, radius, color): self.s = startpoint self.e = endpoint self.r = radius self.col = color def intersection(self, l): q = l.d.dot(l.o - self.c)**2 - (l.o - self.c).dot(l.o - self.c) + self.r**2 if q < 0: return Intersection( Vector(0,0,0), -1, Vector(0,0,0), self) else: d = -l.d.dot(l.o - self.c) d1 = d - sqrt(q) d2 = d + sqrt(q) if 0 < d1 and ( d1 < d2 or d2 < 0): return Intersection(l.o+l.d*d1, d1, self.normal(l.o+l.d*d1), self) elif 0 < d2 and ( d2 < d1 or d1 < 0): return Intersection(l.o+l.d*d2, d2, self.normal(l.o+l.d*d2), self) else: return Intersection( Vector(0,0,0), -1, Vector(0,0,0), self) def normal(self, b): return (b - self.c).normal() class LightBulb( Sphere ): pass class Plane( object ): "infinite, no endings" def __init__(self, point, normal, color): self.n = normal self.p = point self.col = color def intersection(self, l): d = l.d.dot(self.n) if d == 0: return Intersection( vector(0,0,0), -1, vector(0,0,0), self) else: d = (self.p - l.o).dot(self.n) / d return Intersection(l.o+l.d*d, d, self.n, self) class Rectangle( object ): "not done. like a plane, but is limited to the shape of a defined rectangle" def __init__(self, point, normal, color): self.n = normal self.p = point self.col = color def intersection(self, ray): desti = ray.dest.dot(self.n) if desti == 0: #?? return Intersection( vector(0,0,0), -1, vector(0,0,0), self) else: desti = (self.p - ray.orig).dot(self.n) / desti return Intersection(ray.orig+ray.desti*desti, desti, self.n, self) class RectangleBox( object ): "not done. consists of multiple rectangle objects as its sides" pass class AnimatedObject( object ): def __init__(self, *objs): self.objs = objs def __iter__(self): for obj in self.objs: yield obj def __getitem__(self, index): return self.objs[index] def reverse(self): self.objs = [each for each in reversed(self.objs)] return self #RAY TRACING INTERNAL COMPONENTS class Ray( object ): def __init__(self, origin, direction): self.o = origin self.d = direction class Intersection( object ): "keeps a record of a known intersection bw ray and obj?" def __init__(self, point, distance, normal, obj): self.p = point self.d = distance self.n = normal self.obj = obj def testRay(ray, objects, ignore=None): intersect = Intersection( Vector(0,0,0), -1, Vector(0,0,0), None) for obj in objects: if obj is not ignore: currentIntersect = obj.intersection(ray) if currentIntersect.d > 0 and intersect.d < 0: intersect = currentIntersect elif 0 < currentIntersect.d < intersect.d: intersect = currentIntersect return intersect def trace(ray, objects, light, maxRecur): if maxRecur < 0: return (0,0,0) intersect = testRay(ray, objects) if intersect.d == -1: col = vector(AMBIENT,AMBIENT,AMBIENT) elif intersect.n.dot(light - intersect.p) < 0: col = intersect.obj.col * AMBIENT else: lightRay = Ray(intersect.p, (light-intersect.p).normal()) if testRay(lightRay, objects, intersect.obj).d == -1: lightIntensity = 1000.0/(4*pi*(light-intersect.p).magnitude()**2) col = intersect.obj.col * max(intersect.n.normal().dot((light - intersect.p).normal()*lightIntensity), AMBIENT) else: col = intersect.obj.col * AMBIENT return col def gammaCorrection(color,factor): return (int(pow(color.x/255.0,factor)*255), int(pow(color.y/255.0,factor)*255), int(pow(color.z/255.0,factor)*255)) #USER FUNCTIONS class Camera: def __init__(self, cameraPos, zoom=50.0, xangle=-5, yangle=-5): self.pos = cameraPos self.zoom = zoom self.xangle = xangle self.yangle = yangle def renderScene(camera, lightSource, objs, imagedims, savepath): imgwidth,imgheight = imagedims img = PIL.Image.new("RGB",imagedims) #objs.append( LightBulb(lightSource, 0.2, Vector(*white)) ) print ("rendering 3D scene") t=time.clock() for x in range(imgwidth): #print x for y in range(imgheight): ray = Ray( camera.pos, (Vector(x/camera.zoom+camera.xangle,y/camera.zoom+camera.yangle,0)-camera.pos).normal()) col = trace(ray, objs, lightSource, 10) img.putpixel((x,imgheight-1-y),gammaCorrection(col,GAMMA_CORRECTION)) print ("time taken", time.clock()-t) img.save(savepath) def renderAnimation(camera, lightSource, staticobjs, animobjs, imagedims, savepath, saveformat): "NOTE: savepath should not have file extension, but saveformat should have a dot" time = 0 while True: print ("time",time) timesavepath = savepath+"_"+str(time)+saveformat objs = [] objs.extend(staticobjs) objs.extend([animobj[time] for animobj in animobjs]) renderScene(camera, lightSource, objs, imagedims, timesavepath) time += 1 #SOME LIGHTNING OPTIONS AMBIENT = 0.05 #daylight/nighttime GAMMA_CORRECTION = 1/2.2 #lightsource strength? #COLORS red = (255,0,0) yellow = (255,255,0) green = (0,255,0) blue = (0,0,255) grey = (120,120,120) white = (255,255,255) purple = (200,0,200) def origtest(): print ("") print ("origtest") #BUILD THE SCENE imagedims = (1000,1000) savepath = "3dscene_orig.png" objs = [] objs.append(Sphere( Vector(-2,0,-10), 2, Vector(*green))) objs.append(Sphere( Vector(2,0,-10), 3.5, Vector(*red))) objs.append(Sphere( Vector(0,-4,-10), 3, Vector(*blue))) objs.append(Plane( Vector(0,0,-12), Vector(0,0,1), Vector(*grey))) lightSource = Vector(0,10,0) camera = Camera(Vector(0,0,20)) #RENDER renderScene(camera, lightSource, objs, imagedims, savepath) def normaltest(): print ("") print ("normaltest") #BUILD THE SCENE """ the camera is looking down on the surface with the spheres from above the surface is like looking down on the xy axis of the xyz coordinate system the light is down there together with the spheres, except from one of the sides """ imagedims = (1200,1200) savepath = "3dscene.png" objs = [] objs.append(Sphere( Vector(-4, -2, 1), 1, Vector(*red))) objs.append(Sphere( Vector(-2, -2, 1), 1, Vector(*blue))) objs.append(Sphere( Vector(-2, -4, 1), 1, Vector(*green))) objs.append(Plane( Vector(0,0,0), Vector(0,0,1), Vector(*grey))) lightSource = Vector(-2.4, -3, 2) camera = Camera(Vector(-19,-19,2), zoom=2.0, xangle=-30, yangle=-30) #RENDER renderScene(camera, lightSource, objs, imagedims, savepath) def animtest(): print ("") print ("falling ball test") #BUILD THE SCENE imagedims = (200,200) savepath = "3d_fallball" saveformat = ".png" staticobjs = [] staticobjs.append(Sphere( Vector(-4, -2, 1), 1, Vector(*red))) staticobjs.append(Sphere( Vector(-2, -4, 1), 1, Vector(*green))) staticobjs.append(Plane( Vector(0,0,0), Vector(0,0,1), Vector(*purple))) animobjs = [] fallingball = AnimatedObject(Sphere( Vector(-2, -2, 20), 1, Vector(*yellow)), Sphere( Vector(-2, -2, 15), 1, Vector(*yellow)), Sphere( Vector(-2, -2, 9), 1, Vector(*yellow)), Sphere( Vector(-2, -2, 5), 1, Vector(*yellow)), Sphere( Vector(-2, -2, 1), 1, Vector(*yellow))) animobjs.append(fallingball) lightSource = Vector(-4,-4,10) camera = Camera(Vector(0,0,30)) #RENDER renderAnimation(camera, lightSource, staticobjs, animobjs, imagedims, savepath, saveformat) #RUN TESTS #origtest() normaltest() #animtest()
Отредактировано leonid_10 (Янв. 31, 2015 19:10:06)
Офлайн
> Я понимаю, что Питон медленный. Я это знал и собирался как раз изучить swig.
Вот ты чудак. Я тебе пишу что он быстрый, а ты думаешь что медленный. Сначала ВНИМАТЕЛЬНО прочти то что я написал, а потом уже и делай выводы про swig.
> Но, как получить результат промежуточного вычисления, который обычно отображают программы рендера?
Делай мозаичную отрисовку.
Отредактировано Rodegast (Янв. 31, 2015 19:16:06)
Офлайн
Rodegast
> Я понимаю, что Питон медленный. Я это знал и собирался как раз изучить swig.Вот ты чудак. Я тебе пишу что он быстрый, а ты думаешь что медленный. Сначала ВНИМАТЕЛЬНО прочти то что я написал, а потом уже и делай выводы про swig.> Но, как получить результат промежуточного вычисления, который обычно отображают программы рендера?Делай мозаичную отрисовку.
Отредактировано leonid_10 (Янв. 31, 2015 19:40:34)
Офлайн
> Всё-равно непонятно…
Тот алгоритм который сейчас отрисовывает по таймеру 1 пиксел за 1мс (ставить очень маленькие значения задержки не имеет смысла) т.е. его максимальная скорость работы будет не более 1000 пикселей в сек и от языка это никак не зависит. При мозаичной отрисовки по таймеру будет выводится не пиксел, а фрагмент изображения и следовательно производительность будет намного выше.
Отредактировано Rodegast (Янв. 31, 2015 21:11:58)
Офлайн
Rodegast
> Всё-равно непонятно…Тот алгоритм который сейчас отрисовывает по таймеру 1 пиксел за 1мс (ставить очень маленькие значения задержки не имеет смысла) т.е. его максимальная скорость работы будет не более 1000 пикселей в сек и от языка это никак не зависит. При мозаичной отрисовки по таймеру будет выводится не пиксел, а фрагмент изображения и следовательно производительность будет намного выше.
Офлайн