簡體   English   中英

Python OpenGL不會渲染四邊形中的每個三角形

[英]Python OpenGL does not render every Triangle in a Quadrilateral

我有一些代碼可以在OpenGL中使用紋理渲染平坦的表面。 相同的框架使我可以渲染立方體,但平坦的表面似乎可以渲染三個正方形中間的三角形。 效果似乎是信封形狀。

我已經更改了紋理圖像。 我嘗試使用3個通道而不是4個通道加載圖像。相同的框架可以毫無問題地呈現多維數據集。

我可以再次渲染相同的正方形,然后旋轉它或使用三角形代替,但是我更希望理解這個問題。

## Python 3.7

## OpenGL objectsare visualised in pygame

from OpenGL.GL import *
from OpenGL.GLU import *
import pygame
from pygame.locals import *
import sys
import numpy as np
import cv2

cwd = 'C:/Users/berta/Desktop/Python/Open GL/'

coords = np.array([
[0.,1.],
[1.,1.],
[1.,0.],
[0.,0.]
])

graphic_names = [
    'ground'
]

ground_vertices = np.array([
    [-10, -1.5, 10],
    [10, -1.5, 10],
    [-10, -1.5, -300],
    [10, -1.5, -300]
], dtype = np.float64)

def loadGraphics(graphic_names):
    output_dict = {}
    for f in graphic_names:
        img = cv2.imread(cwd + 'Images/' + f + '.png', cv2.IMREAD_UNCHANGED)
        if img.shape[2] == 3:
            alpha = np.uint8(np.ones(img.shape[:2])*255)
            img = np.dstack((img,alpha))
        textureSurface = pygame.Surface(img.shape[:2], pygame.SRCALPHA)
        bv = textureSurface.get_buffer()
        bv.write(img.tostring(), 0)
        textureData = pygame.image.tostring(textureSurface, "RGBA", 1)
        width = textureSurface.get_width()
        height = textureSurface.get_height()
        output_dict[f] = (textureData, width, height)
    return output_dict

graphics = loadGraphics(graphic_names)

def loadTexture(textureData, width, height):
    glEnable(GL_BLEND)
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

    glEnable(GL_TEXTURE_2D)

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height,
                    0, GL_RGBA, GL_UNSIGNED_BYTE, textureData)

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
    return

class FlatSurface:

    def __init__(self, texture_name, input_vertices, n_x, n_z):
        self.texture_name = texture_name
        self.vertices = input_vertices
        # Determines the flat plane and creates tiled squares
        flat_dim_found = False
        for i in range(3):
            if np.all(self.vertices[:,i] == self.vertices[0,i]):
                flat_dim_found = True
                self.flat_dim = i
                break
        if not(flat_dim_found):
            print('No flat dimension has been found!')
            self.flat_dim = 1
        self.y_const = np.mean(self.vertices[:,self.flat_dim])
        x_not_done = True
        for i in range(3):
            if i != self.flat_dim:
                if x_not_done:
                    self.min_x = np.min(self.vertices[:,i])
                    max_x = np.max(self.vertices[:,i])
                    self.x_dim = i
                    x_not_done = False
                else:
                    self.min_z = np.min(self.vertices[:,i])
                    max_z = np.max(self.vertices[:,i])
                    self.z_dim = i
        self.tiles = []
        self.tile_x_width = float(max_x-self.min_x)/float(n_x)
        self.tile_z_width = float(max_z-self.min_z)/float(n_z)
        for x in range(n_x):
            for z in range(n_z):
                self.tiles.append(self.make_tile(x,z))
        self.tiles = np.array(self.tiles, dtype = np.float64)
        print(self.tiles)

    def make_tile(self,x,z):
        # Creates a square tile for a certain index in the bounded shape
        surf = []
        tile = np.array([0,0,0])
        tile[self.flat_dim] = self.y_const
        tile[self.x_dim] = self.min_x + x*self.tile_x_width
        tile[self.z_dim] = self.min_z + z*self.tile_z_width
        surf.append(tile.copy())
        tile[self.z_dim] += self.tile_z_width
        surf.append(tile.copy())
        tile[self.x_dim] += self.tile_x_width
        tile[self.z_dim] -= self.tile_z_width
        surf.append(tile.copy())
        tile[self.z_dim] += self.tile_z_width
        surf.append(tile.copy())
        return surf

    def draw(self):
        # loads texture and draws each square
        loadTexture(*graphics[self.texture_name])
        glBegin(GL_QUADS)
        for surf in self.tiles:
            for vertex, coord in zip(surf, coords):
                glTexCoord2f(*coord)
                glVertex3fv(vertex)
            ## A shameful hack to stop envelopes appearing
            #for vertex, coord in zip(surf[::-1], coords):
            #   glTexCoord2f(*coord)
            #   glVertex3fv(vertex)
        glEnd()


def main():
    pygame.init()
    display = (1200,800)
    pygame.display.set_mode(display, DOUBLEBUF|OPENGL|OPENGLBLIT)
    gluPerspective(45, (display[0]/display[1]), 0.99 , 20.0)
    glTranslatef( 0., 0., -10. )
    glRotate(0, 0, 0, 0)
    x_move = 0
    z_move = 0
    speed = 0.01

    ground = FlatSurface('ground', ground_vertices, 4, 62)

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

        m = glGetDoublev(GL_MODELVIEW_MATRIX) # perspective matrix

        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
        ground.draw()
        glTranslate(x_move,0,z_move+speed)
        pygame.display.flip()
        pygame.time.wait(10)


main()

四邊形的坐標如下所示,並且符合預期:

[[   5.   -1.   -5.]
[   5.   -1.    0.]
[  10.   -1.   -5.]
[  10.   -1.    0.]]

[[   5.   -1.    0.]
[   5.   -1.    5.]
[  10.   -1.    0.]
[  10.   -1.    5.]]

[[   5.   -1.    5.]
[   5.   -1.   10.]
[  10.   -1.    5.]
[  10.   -1.   10.]]]

輸出顯示在屏幕截圖中。

信封而不是正方形

您的頂點順序錯誤。

您對每個四邊形使用以下順序:

1---2
|   |
3---4

但這應該是:

1---2
|   |
4---3

問題在於類make_tile中的FlatSurface方法,該方法以錯誤的順序為Quad基本體創建了頂點。
頂點必須圍繞四邊形以循環順序排列。 例如:

           1         2
       z    +--------+
       ^    |        |
       |    |        |
       |    |        |
            +--------+
min (x, z) 0          3
             -----> x

它一定要是:

class FlatSurface

    # [...]

    def make_tile(self,x,z):
        # Creates a square tile for a certain index in the bounded shape
        surf = []
        tile = np.array([0,0,0])
        tile[self.flat_dim] = self.y_const
        tile[self.x_dim] = self.min_x + x*self.tile_x_width
        tile[self.z_dim] = self.min_z + z*self.tile_z_width
        surf.append(tile.copy())
        tile[self.z_dim] += self.tile_z_width
        surf.append(tile.copy())
        tile[self.x_dim] += self.tile_x_width
        surf.append(tile.copy())
        tile[self.z_dim] -= self.tile_z_width
        surf.append(tile.copy())
        return surf

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM