凹面 GL_POLYGON 不着色?

问题描述 投票:0回答:2

当我尝试在 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();
}

输出:

https://i.sstatic.net/BLMSJ.png

c++ c opengl polygon opengl-compat
2个回答
15
投票

GL_POLYGON
仅适用于凸多边形:

GL_POLYGON
:绘制单个凸多边形。顶点 1N 定义了这个多边形。

对于凹多边形,您至少有两个选择:

  1. 对多边形进行三角剖分并使用

    GL_TRIANGLES

  2. 使用模板缓冲区技巧


0
投票

如果您的多边形非常复杂,例如我的科赫雪花,您将无法使用三角测量。由于多边形的形状太分形,为了使用三角测量,您必须创建一个名为“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()

© www.soinside.com 2019 - 2024. All rights reserved.