在python中,我希望尽可能快地从3D三角形栅格化2D三角形,并剪切超出z边界的像素。我可以将3D坐标转换为2D,我似乎无法进行光栅化工作。我使用的是设置像素的方法,其中(x,y,颜色)和(0,0)位于左上角。
感谢您的帮助。 这是我使用的三角形代码。
def triangle(self,v = vec2(0,0),v1 = vec2(0,0),v2 = vec2(0,0), colour = 0xFFFFFF):
sort = sortVecByY(v,v1,v2)
a = sort[0]
b = sort[1]
c = sort[2]
if b.y == c.y:
self.flatBottomTri(a,b,c,colour)
elif a.y == b.y:
self.flatTopTri(a,b,c,colour)
else:
d = vec2(int(a.x + (float((b.y-a.y)/(c.y-a.y))) * (c.x - a.x)),b.y)
self.flatBottomTri(a,b,d,colour)
self.flatTopTri(b,d,c,colour)
def flatBottomTri(self,v1,v2,v3,colour):
r1 = (v2.y - v1.y)
s1 = 0
if r1 != 0.0:
s1 = (v2.x - v1.x) / r1
r2 = (v3.y - v1.y)
s2 = 0
if r2 != 0.0:
s2 = (v3.x - v1.x) / (v3.y - v1.y)
x1 = v1.x
x2 = v1.x + 0.5
for sy in range(v1.y,v2.y):
for x in range(int(x1),int(x2)):
self.set(x,sy,colour)
x1 += s1
x2 += s2
def flatTopTri(self,v1,v2,v3,colour):
s1 = (v3.x - v1.x) / (v3.y - v1.y)
s2 = (v3.x - v2.x) / (v3.y - v2.y)
x1 = v3.x
x2 = v3.x + 0.5
for sy in range(v3.y,v1.y,-1):
x1 -= s1
x2 -= s2
for x in range(int(x1),int(x2)):
self.set(x,sy,colour)
答案 0 :(得分:0)
对于我的 shapeimager 包 (github.com/pedrohasselmann/shapeimager),我让下面的类工作得非常快。
它是用 Cython 编写的,并且摆脱了 GIL。 TriangleAccumulator() 从表示其角的 3D 位置的向量中返回像素填充的三角形。 它在 0.3 秒内运行了 50 万个三角形。
cdef bint point_in_triangle(float[::1] xp,
float[::1] yp,
float x,
float y) nogil:
cdef:
float dX = x - xp[0]
float dY = y - yp[0]
float dX20 = xp[2] - xp[0]
float dY20 = yp[2] - yp[0]
float dX10 = xp[1] - xp[0]
float dY10 = yp[1] - yp[0]
float s = (dY20*dX) - (dX20*dY)
float t = (dX10*dY) - (dY10*dX)
float D = (dX10*dY20) - (dY10*dX20)
if D>0:
return (s>=0) & (t>=0) & ((s + t)<=D)
else:
return (s<=0) & (t<=0) & ((s + t)>=D)
cdef (float, float) minmax(float[::1] arr) nogil:
cdef float min = INFINITY
cdef float max = -INFINITY
cdef ssize_t i, L = arr.shape[0]
for i in range(L):
if arr[i] < min:
min = arr[i]
if arr[i] > max:
max = arr[i]
return min, max
cdef class TriangleAccumulator:
cdef:
short width, height
int n
unsigned int[:, ::1] image
unsigned short[::1] rr, cc
unsigned int[::1] ff
def __cinit__(self, short width,
short height,
short x):
self.n = 0
self.width = width
self.height = height
shape = (height, width)
self.image = np.zeros(shape, dtype=uint32)
self.rr = np.empty(x*(self.width-1)*(self.height-1), dtype=uint16, order='C')
self.cc = np.empty(x*(self.width-1)*(self.height-1), dtype=uint16, order='C')
self.ff = np.empty(x*(self.width-1)*(self.height-1), dtype=uint32, order='C')
def reset(self):
self.image[:, :] = 0
@cython.boundscheck(False) # Deactivate bounds checking
@cython.wraparound(False) # Deactivate negative indexing.
@cython.nonecheck(False)
@cython.cdivision(True)
cdef void superimpose_polygon(self,
float[::1] ya,
float[::1] xa,
unsigned int value) nogil:
cdef float minya, maxya, minxa, maxxa
minya, maxya = minmax(ya)
minxa, maxxa = minmax(xa)
cdef:
ssize_t minr = int(max(0, minya))
ssize_t maxr = int(ceil(maxya))
ssize_t minc = int(max(0, minxa))
ssize_t maxc = int(ceil(maxxa))
unsigned short r, c
maxr = min(self.height -1, maxr)
maxc = min(self.width -1, maxc)
for r in range(minr, maxr+1):
for c in range(minc, maxc+1):
if point_in_triangle(xa, ya, c, r):#point_in_polygon(xa, ya, c, r):
self.image[r, c] = value
self.rr[self.n] = r
self.cc[self.n] = c
self.ff[self.n] = value
self.n +=1