当我尝试在 OpenGL 中使用
GL_POLYGON
时遇到问题。我不知道如何解释这一点,但我的所有顶点都与第一个顶点相连。当我尝试为对象着色时出现问题。我想画一个简单的物体。
void TOP (float x1, float y1, float x2, float h,float n)
{
float r = x2-x1;
if(n==1){glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);} // FOR FILL OR NO FILL OBJECT
glBegin(GL_POLYGON);
glVertex2f(x1,y1);
glVertex2f(x2,y1);
glVertex2f(x2,y1+h/7);
y1=y1+h/7;
glVertex2f(x2-r/5,y1+h/7);
x2=x2-r/5; y1=y1+h/7;
glVertex2f(x2,y1+2*h/7);
y1=y1+2*h/7;
glVertex2f(x2+r/5,y1+h/7);
y1=y1+h/7; x2=x2+r/5;
glVertex2f(x2,y1+2*h/7);
cout<<y1<<endl;
y1=y1+2*h/7;
glVertex2f(x2-r/5,y1); x2=x2-r/5;
glVertex2f(x2,y1-h/7); y1=y1-h/7;
glVertex2f(x2-r/5,y1);x2=x2-r/5;
glVertex2f(x2,y1+h/7); y1=y1+h/7;
glVertex2f(x2-r/5,y1);x2=x2-r/5;
glVertex2f(x2,y1-h/7); y1=y1-h/7;
glVertex2f(x2-r/5,y1);x2=x2-r/5;
glVertex2f(x2,y1+h/7); y1=y1+h/7;
glVertex2f(x2-r/5,y1);x2=x2-r/5;
glVertex2f(x2,y1-2*h/7);y1=y1-2*h/7;
glVertex2f(x2+r/5,y1-h/7);y1=y1-h/7; x2=x2+r/5;
glVertex2f(x2,y1-2*h/7); y1=y1-2*h/7;
glVertex2f(x2-r/5,y1-h/7); y1=y1-h/7;x2=x2-r/5;
glVertex2f(x2,y1-h/7);
glEnd();
}
输出:
GL_POLYGON
仅适用于凸多边形:
:绘制单个凸多边形。顶点 1 到 N 定义了这个多边形。GL_POLYGON
对于凹多边形,您至少有两个选择:
对多边形进行三角剖分并使用
GL_TRIANGLES
。
如果您的多边形非常复杂,例如我的科赫雪花,您将无法使用三角测量。由于多边形的形状太分形,为了使用三角测量,您必须创建一个名为“point_in_polygon”的函数,在将纹理应用到表面之前检查像素是否在多边形内部。
import math
import random
import numpy as np
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
def create_sin_lookup_table(size, amplitude=1.0, offset=0.0):
return [math.sin(2 * math.pi * i / size) * amplitude + offset for i in range(size)]
def create_cos_lookup_table(size, amplitude=1.0, offset=0.0):
return [math.cos(2 * math.pi * i / size) * amplitude + offset for i in range(size)]
sin_table = create_sin_lookup_table(360)
cos_table = create_cos_lookup_table(360)
def create_sinus_plasma(width, height, freq1, freq2, freq3):
amplitude = 127.5
offset = 127.5
x = np.linspace(0, 2 * np.pi, width)
y = np.linspace(0, 2 * np.pi, height)
X, Y = np.meshgrid(x, y)
R = np.sin(freq1 * X + freq1 * Y) + np.sin(freq2 * X - freq2 * Y)
G = np.sin(freq2 * X + freq2 * Y) + np.sin(freq3 * X - freq3 * Y)
B = np.sin(freq3 * X + freq3 * Y) + np.sin(freq1 * X - freq1 * Y)
R = np.power(np.abs(R), 1.5) * np.sign(R) * amplitude + offset
G = np.power(np.abs(G), 1.5) * np.sign(G) * amplitude + offset
B = np.power(np.abs(B), 1.5) * np.sign(B) * amplitude + offset
R = np.clip(R, 0, 255).astype(np.uint8)
G = np.clip(G, 0, 255).astype(np.uint8)
B = np.clip(B, 0, 255).astype(np.uint8)
plasma = np.stack((R, G, B), axis=-1)
return plasma
def koch_snowflake(points, depth, iteration_modes):
if depth == 0:
return points
new_points = []
mode = iteration_modes[len(iteration_modes) - depth] if depth <= len(iteration_modes) else 2
for i in range(len(points)):
p1 = points[i]
p2 = points[(i + 1) % len(points)]
a = ((2 * p1[0] + p2[0]) / 3, (2 * p1[1] + p2[1]) / 3)
b = ((p1[0] + 2 * p2[0]) / 3, (p1[1] + 2 * p2[1]) / 3)
if mode == 0:
angle_index = int((60 / 360) * len(sin_table)) % len(sin_table)
elif mode == 1:
angle_index = int((-60 / 360) * len(sin_table)) % len(sin_table)
else:
angle_index = int((random.choice([60, -60]) / 360) * len(sin_table)) % len(sin_table)
dx, dy = b[0] - a[0], b[1] - a[1]
cx = dx * cos_table[angle_index] - dy * sin_table[angle_index] + a[0]
cy = dx * sin_table[angle_index] + dy * cos_table[angle_index] + a[1]
c = (cx, cy)
new_points.extend([p1, a, c, b])
return koch_snowflake(new_points, depth - 1, iteration_modes)
def rotate_point(point, center, rotation_angle):
dx = point[0] - center[0]
dy = point[1] - center[1]
cos_angle = math.cos(math.radians(rotation_angle))
sin_angle = math.sin(math.radians(rotation_angle))
new_x = dx * cos_angle - dy * sin_angle + center[0]
new_y = dx * sin_angle + dy * cos_angle + center[1]
return new_x, new_y
def point_in_polygon(x, y, polygon):
num = len(polygon)
j = num - 1
odd = False
for i in range(num):
if ((polygon[i][1] > y) != (polygon[j][1] > y)) and \
(x < (polygon[j][0] - polygon[i][0]) * (y - polygon[i][1]) / (polygon[j][1] - polygon[i][1]) + polygon[i][0]):
odd = not odd
j = i
return odd
def render_snowflake_with_plasma(snowflake, plasma):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
width, height = plasma.shape[1], plasma.shape[0]
# Zeichne die gefüllte Fläche mit der Textur
glBegin(GL_POINTS)
for y in range(height):
for x in range(width):
if point_in_polygon(x, y, snowflake):
color = plasma[y, x] / 255.0
glColor3f(color[0], color[1], color[2])
glVertex2f(x / (width / 2) - 1, -(y / (height / 2) - 1))
glEnd()
# Zeichne die Hüllkurve der Schneeflocke in konstantem Blau
glLineWidth(3.0)
glDisable(GL_TEXTURE_2D)
glColor3f(0.0, 0.0, 1.0)
glBegin(GL_LINE_LOOP)
for point in snowflake:
glVertex2f(point[0] / (width / 2) - 1, -(point[1] / (height / 2) - 1))
glEnd()
pygame.display.flip()
def main():
pygame.init()
display = (800, 600)
pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
gluOrtho2D(-1, 1, -1, 1)
side_length = 260
height = math.sqrt(3) / 2 * side_length
base_triangle = [
(400, 300 - (2 / 3) * height),
(400 - side_length / 2, 300 + (1 / 3) * height),
(400 + side_length / 2, 300 + (1 / 3) * height)
]
plasma = create_sinus_plasma(800, 600, 0.2, 0.4, 1.5)
clock = pygame.time.Clock()
rotation_angle = 0
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
return
iteration_depth = 2
iteration_modes = [0, 0, 0, 0, 0]
snowflake = koch_snowflake(base_triangle, iteration_depth, iteration_modes)
rotated_snowflake = [rotate_point(p, (400, 300), rotation_angle) for p in snowflake]
render_snowflake_with_plasma(rotated_snowflake, plasma)
rotation_angle = (rotation_angle + 1) % 360
clock.tick(60)
if __name__ == "__main__":
main()