[英]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.