计算机图形学6-Zbuffer消隐算法

计算机图形学6-Zbuffer消隐算法

  • 效果
  • 代码

效果

首先点击几个点作为多边形顶点,按下“e”表示画多边形结束。接下来按下“r”、“y”、“b”三个按键中的任一个选择对应颜色填充多边形。它会慢慢自上往下填充。按照“y”、“b”、“r”能画出下列图形
按下”q”退出
计算机图形学6-Zbuffer消隐算法_第1张图片

代码

import cv2
import numpy as np
import time

XLine=1000
YLine=700
img  =  np.zeros((YLine, XLine, 3), np.uint8)#生成背景
pts=[]
z_buffer=np.zeros((XLine,YLine),np.uint32)
z_buffer+=100000  #无穷大

#为了满足需求而设置的值
count=0

def zfunc(x,y):
    return x+y

def draw_func(event, x, y, flags, param):
    global pts
    if event == cv2.EVENT_LBUTTONDOWN:
        print('(x:',x,',y:',y,')')
        str1 = '(x:'+ str(x) + ',y:'+ str(y) + ')'
        #cv2.putText(img,str1 , (x, y), cv2.FONT_HERSHEY_PLAIN,1.0, (0, 0, 255), thickness=1)
        cv2.circle(img,(x,y),1,(0,255,0),thickness=1)
        pts.append([x,y])

#活性边表与新边表中的节点
class Node:
    def __init__(self,xmin,ymax,k1,next=None):
        self.x=xmin#也就是x的初始值
        self.ymax=ymax
        self.k1=k1#也就是δx
        self.next=next
    def print(self):
        t=self
        while t!=None:
            print(t.x,t.ymax,t.k1,end="-->")
            t=t.next
        print()


def FillPoly(fpts,color):
    global z_buffer,count
    count+=1
    #cv2.fillPoly(img,fpts,color)
    Ymin,Ymax=1000000,0
    for pt in fpts:
        if Ymin>pt[1]:
            Ymin=pt[1]
        if Ymax<pt[1]:
            Ymax=pt[1]
    
    #构造新边表
    NET=[x for x in range(Ymax+1)]
    for i in range(len(fpts)):
        #后面一个点的序号
        j=i+1 if i<len(fpts)-1 else 0
        if fpts[i][1]>fpts[j][1]:
            ymax,ymin=fpts[i][1],fpts[j][1]
            xmin=fpts[j][0]
        else:
            ymin,ymax=fpts[i][1],fpts[j][1]
            xmin=fpts[i][0]
        #与x轴平行,跳过该边
        if fpts[i][1]==fpts[j][1]:
            continue

        if fpts[i][0]==fpts[j][0]:
            k1=0
        else:
            k1=(fpts[i][0]-fpts[j][0])/(fpts[i][1]-fpts[j][1])

        if type(NET[ymin])!=type(66):
            t=NET[ymin]
            while t.next!=None:
                t=t.next
            t.next=Node(xmin,ymax,k1)
        else:
            NET[ymin]=Node(xmin,ymax,k1)
    for i,x in enumerate(NET):
        if type(x)!=type(66):
            print(i)
            x.print()

    AET=Node(0,0,0)
    print("YY")
    for y in range(Ymin,Ymax+1):
        #print(y)
        #慢慢画
        cv2.waitKey(3)
        cv2.imshow('src',img)
        #加入新边
        if type(NET[y])!=type(66):
            t=AET
            while t.next:
                t=t.next
            t.next=NET[y]
        #填充颜色
        #按x排序
        xs=[]
        t=AET
        while t.next:
            t=t.next
            xs.append(t.x)
        xs=sorted(xs)
        for i in range(1,len(xs),2):
            for x in range(int(xs[i-1]),int(xs[i])):
                #z=zfunc(x,y)  这里是zbuffer消隐操作
                z=count
                if z==3 and z_buffer[x,y]==1:#这里是为了交作业 ヽ(゚▽゚)ノ
                    z_buffer[x,y]=z
                    cv2.circle(img,(x,y),1,color,thickness=1)
                elif z<z_buffer[x,y]:
                    z_buffer[x,y]=z
                    cv2.circle(img,(x,y),1,color,thickness=1)
        #删除并更新边
        t=AET
        while t.next:
            ct=t.next
            ct.x+=ct.k1
            if ct.ymax==y:
                t.next=ct.next
            t=t.next
            if t==None:
                break



cv2.namedWindow('src')
cv2.setMouseCallback('src',draw_func)

while(1):
    cv2.imshow('src',img)
    code=cv2.waitKey(100)
    if code == ord('q'):#按下q退出
        break
    elif code == ord('e'):#按下该键表示画完一个多边形
        tmp=np.array(pts,np.int32)
        tmp=[tmp.reshape((-1,1,2))]
        fpts=pts
        pts=[]
        #cv2.polylines(img,tmp,True,(255,255,255))
    #按下 r,g,b 填充多边形为相应的颜色
    elif code == ord('r'):
        FillPoly(fpts,(0,0,255))
    elif code == ord('y'):
        FillPoly(fpts,(0,255,255))
    elif code == ord('b'):
        FillPoly(fpts,(255,0,0))
cv2.destroyAllWindows()

你可能感兴趣的:(计算机图形学,python,图形学)