纹理 3D 图形(圆柱体)

Texture the 3D figure (cylinder)

我需要对我的圆柱体进行纹理处理,我有 texture.png 并且我已经做了一个 多边形网格(带三角形)。

如果你需要的话,这是代码 pastebin

import pyglet
import pyglet.gl as pgl
from pyglet.window import key
import math

win = pyglet.window.Window(1300, 1000, resizable=True)

WINDOW = 1000
tr = 90
INCREMENT = 5
transparant = False
xRotation = -70
zRotation = -30
yRotation = 180
zoom = 1
far = 100
dist = 35
x = -180
y = 70
z = 0
light = False

param = 0
t_prev = -5
start_loop = False
run_loop = False



def run_loop(dt):
    on_draw()


def draw_figure():
    angle = 0
    t = 0
    x = y = z = 0
    a = 50
    b = 100

    if not transparant:
        pgl.glPolygonMode(pgl.GL_FRONT_AND_BACK, pgl.GL_FILL)
    else:
        pgl.glPolygonMode(pgl.GL_FRONT_AND_BACK, pgl.GL_LINE)
    pgl.glBegin(pgl.GL_TRIANGLE_STRIP)
    for i in range(0, tr + 1):
        pgl.glColor3ub(0, 0, 0)
        if i >= 1:
            t1 = a1
            t2 = a2
            t3 = a3
        a1 = x + a * math.cos(i * 2 * math.pi / tr)
        a2 = y + b * math.sin(i * 2 * math.pi / tr)
        a3 = z + 8
        pgl.glVertex3f(a1, a2, a3)
        if i >= 1:
            pgl.glNormal3f((b2 - t2) * (a3 - b3) - (b3 - t3) * (a2 - b2), (b3 - t3) * (a1 - b1) - (b1 - t1) * (a3 - b3),
                           (b1 - t1) * (a2 - b2) - (b2 - t2) * (a1 - b1))
        b1 = x
        b2 = y
        b3 = z + 8
        pgl.glVertex3f(b1, b2, b3)
    pgl.glEnd()
    for j in range(1, 27):
        pgl.glBegin(pgl.GL_TRIANGLE_STRIP)
        pgl.glColor3ub(0, 0, 0)
        x1 = a * math.cos(0)
        y1 = b * math.sin(0)
        a1 = x1 * math.cos(t * math.pi / 360) + y1 * math.sin(t * math.pi / 360)
        a2 = - x1 * math.sin(t * math.pi / 360) + y1 * math.cos(t * math.pi / 360)
        a3 = z + j * 8
        pgl.glVertex3f(a1, a2, a3)
        x1 = a * math.cos(0)
        y1 = b * math.sin(0)
        b1 = x1 * math.cos((t + 16) * math.pi / 360) + y1 * math.sin((t + 16) * math.pi / 360)
        b2 = - x1 * math.sin((t + 16) * math.pi / 360) + y1 * math.cos((t + 16) * math.pi / 360)
        b3 = z + j * 8 + 8
        pgl.glVertex3f(b1, b2, b3)
        for i in range(1, tr + 1):
            pgl.glColor3ub(0, 0, 0)
            x1 = a * math.cos(i * 2 * math.pi / tr)
            y1 = b * math.sin(i * 2 * math.pi / tr)
            t1 = a1
            t2 = a2
            t3 = a3
            a1 = x1 * math.cos(t * math.pi / 360) + y1 * math.sin(t * math.pi / 360)
            a2 = - x1 * math.sin(t * math.pi / 360) + y1 * math.cos(t * math.pi / 360)
            a3 = z + j * 8
            pgl.glNormal3f((b2 - t2) * (a3 - b3) - (b3 - t3) * (a2 - b2), (b3 - t3) * (a1 - b1) - (b1 - t1) * (a3 - b3),
                           (b1 - t1) * (a2 - b2) - (b2 - t2) * (a1 - b1))
            pgl.glVertex3f(a1, a2, a3)
            x1 = a * math.cos(i * 2 * math.pi / tr)
            y1 = b * math.sin(i * 2 * math.pi / tr)
            b1 = x1 * math.cos((t + 16) * math.pi / 360) + y1 * math.sin((t + 16) * math.pi / 360)
            b2 = - x1 * math.sin((t + 16) * math.pi / 360) + y1 * math.cos((t + 16) * math.pi / 360)
            b3 = z + j * 8 + 8
            pgl.glVertex3f(b1, b2, b3)
        t = t + 16
        pgl.glEnd()
    pgl.glBegin(pgl.GL_TRIANGLE_STRIP)
    t = 416
    z = z + 144
    angle = angle + t
    for i in range(0, tr + 1):
        pgl.glColor3ub(0, 0, 0)
        x1 = x + a * math.cos(i * 2 * math.pi / tr)
        y1 = y + b * math.sin(i * 2 * math.pi / tr)
        x2 = x1 * math.cos(t * math.pi / 360) + y1 * math.sin(t * math.pi / 360)
        y2 = - x1 * math.sin(t * math.pi / 360) + y1 * math.cos(t * math.pi / 360)
        if i >= 1:
            t1 = a1
            t2 = a2
            t3 = a3
        a1 = x2
        a2 = y2
        a3 = z + 72
        pgl.glVertex3f(a1, a2, a3)
        if i >= 1:
            pgl.glNormal3f((b2 - t2) * (a3 - b3) - (b3 - t3) * (a2 - b2), (b3 - t3) * (a1 - b1) - (b1 - t1) * (a3 - b3),
                           (b1 - t1) * (a2 - b2) - (b2 - t2) * (a1 - b1))
        b1 = x
        b2 = y
        b3 = z + 72
        pgl.glVertex3f(b1, b2, b3)
        angle = angle + i
    pgl.glEnd()


@win.event
def on_draw():
    global x, y, z, start_loop, run_loop, param, t_prev, zRotation



    pgl.glClearColor(0.3, 0.3, 0.3, 0.0)
    pgl.glEnable(pgl.GL_DEPTH_TEST)
    if light:
        pgl.glEnable(pgl.GL_LIGHTING)
        pgl.glLightModelf(pgl.GL_LIGHT_MODEL_TWO_SIDE, pgl.GL_TRUE)
        pgl.glEnable(pgl.GL_NORMALIZE)
    pgl.glClear(pgl.GL_COLOR_BUFFER_BIT | pgl.GL_DEPTH_BUFFER_BIT)

    pgl.glLoadIdentity()
    pgl.glViewport(0, 0, 1300, 1000)
    pgl.glMatrixMode(pgl.GL_PROJECTION)
    pgl.glLoadIdentity()
    pgl.glOrtho(-1300 / 4, 1300 / 4, -1000 / 4, 1000 / 4, -400, 600)
    pgl.glMatrixMode(pgl.GL_MODELVIEW)
    pgl.glLoadIdentity()

    if light:
        material_diffuse = [1.0, 1.0, 1.0, 1.0]
        pgl.glMaterialfv(pgl.GL_FRONT_AND_BACK, pgl.GL_DIFFUSE,
                         (pgl.GLfloat * len(material_diffuse))(*material_diffuse))

        light5_diffuse = [1.0, 0.0, 0.0];

        light5_position = [0.5, 0.5, 1.0, 0];

        pgl.glEnable(pgl.GL_LIGHT5);

        pgl.glLightfv(pgl.GL_LIGHT5, pgl.GL_DIFFUSE, (pgl.GLfloat * len(light5_diffuse))(*light5_diffuse));

        pgl.glLightfv(pgl.GL_LIGHT5, pgl.GL_POSITION, (pgl.GLfloat * len(light5_position))(*light5_position));

        pgl.glLightf(pgl.GL_LIGHT5, pgl.GL_CONSTANT_ATTENUATION, 0.0);

        pgl.glLightf(pgl.GL_LIGHT5, pgl.GL_LINEAR_ATTENUATION, 0.4);

        pgl.glLightf(pgl.GL_LIGHT5, pgl.GL_QUADRATIC_ATTENUATION, 0.8);

        light6_diffuse = [0.0, 1.0, 0.0];

        light6_position = [0.5 * math.cos(2 * math.pi / 3), 0.5 * math.sin(2 * math.pi / 3), 1.0, 0];

        pgl.glEnable(pgl.GL_LIGHT6);

        pgl.glLightfv(pgl.GL_LIGHT6, pgl.GL_DIFFUSE, (pgl.GLfloat * len(light6_diffuse))(*light6_diffuse));

        pgl.glLightfv(pgl.GL_LIGHT6, pgl.GL_POSITION, (pgl.GLfloat * len(light6_position))(*light6_position));

        pgl.glLightf(pgl.GL_LIGHT6, pgl.GL_CONSTANT_ATTENUATION, 0.0);

        pgl.glLightf(pgl.GL_LIGHT6, pgl.GL_LINEAR_ATTENUATION, 0.4);

        pgl.glLightf(pgl.GL_LIGHT6, pgl.GL_QUADRATIC_ATTENUATION, 0.8);

        light7_diffuse = [0.0, 0.0, 1.0];

        light7_position = [0.5 * math.cos(4 * math.pi / 3), 0.5 * math.sin(4 * math.pi / 3), 1.0, 0];

        pgl.glEnable(pgl.GL_LIGHT7);

        pgl.glLightfv(pgl.GL_LIGHT7, pgl.GL_DIFFUSE, (pgl.GLfloat * len(light7_diffuse))(*light7_diffuse));

        pgl.glLightfv(pgl.GL_LIGHT7, pgl.GL_POSITION, (pgl.GLfloat * len(light7_position))(*light7_position));

        pgl.glLightf(pgl.GL_LIGHT7, pgl.GL_CONSTANT_ATTENUATION, 0.0);

        pgl.glLightf(pgl.GL_LIGHT7, pgl.GL_LINEAR_ATTENUATION, 0.4);

        pgl.glLightf(pgl.GL_LIGHT7, pgl.GL_QUADRATIC_ATTENUATION, 0.8);

    pgl.glPolygonMode(pgl.GL_FRONT_AND_BACK, pgl.GL_FILL)
    pgl.glPushMatrix()
    pgl.glTranslatef(x, y, z)
    pgl.glRotatef(xRotation, 1, 0, 0)
    pgl.glRotatef(yRotation, 0, 1, 0)
    pgl.glRotatef(zRotation, 0, 0, 1)
    pgl.glScalef(zoom, zoom, zoom)

    draw_figure()

    if start_loop:
        start_loop = False
        run_loop = True
        x = ((1 - (param / 100)) ** 3) * (-180) + 3 * (param / 100) * ((1 - (param / 100)) ** 2) * (100) + 3 * (
                    (param / 100) ** 2) * (
                    1 - (param / 100)) * (0) + ((param / 100) ** 3) * (200)
        y = ((1 - (param / 100)) ** 3) * 70 + 3 * (param / 100) * ((1 - (param / 100)) ** 2) * (140) + 3 * (
                    (param / 100) ** 2) * (
                    1 - (param / 100)) * (140) + ((param / 100) ** 3) * (
                70)
        z = ((1 - (param / 100)) ** 3) * 0 + 3 * (param / 100) * ((1 - (param / 100)) ** 2) * (100) + 3 * (
                    (param / 100) ** 2) * (
                    1 - (param / 100)) * (100) + ((param / 100) ** 3) * (
                0)

    elif run_loop:
        if param < 100 and param > t_prev:
            zRotation += INCREMENT
            param = param + 1
            t_prev = t_prev + 1
            if (param == 100):
                t_prev = 105
            x = ((1 - (param / 100)) ** 3) * (-180) + 3 * (param / 100) * ((1 - (param / 100)) ** 2) * (100) + 3 * (
                        (param / 100) ** 2) * (1 - (param / 100)) * (0) + ((param / 100) ** 3) * (200)
            y = ((1 - (param / 100)) ** 3) * 70 + 3 * (param / 100) * ((1 - (param / 100)) ** 2) * (140) + 3 * (
                        (param / 100) ** 2) * (1 - (param / 100)) * (140) + ((param / 100) ** 3) * (
                    70)
            z = ((1 - (param / 100)) ** 3) * 0 + 3 * (param / 100) * ((1 - (param / 100)) ** 2) * (100) + 3 * (
                        (param / 100) ** 2) * (1 - (param / 100)) * (100) + ((param / 100) ** 3) * (
                    0)
            print(param)
            print("плюс")
        if param > 0 and param < t_prev:
            zRotation -= INCREMENT
            param = param - 1
            t_prev = t_prev - 1
            if (param == 0):
                t_prev = -5
            x = ((1 - (param / 100)) ** 3) * (-180) + 3 * (param / 100) * ((1 - (param / 100)) ** 2) * (100) + 3 * (
                    (param / 100) ** 2) * (1 - (param / 100)) * (0) + ((param / 100) ** 3) * (200)
            y = ((1 - (param / 100)) ** 3) * 70 + 3 * (param / 100) * ((1 - (param / 100)) ** 2) * (140) + 3 * (
                    (param / 100) ** 2) * (1 - (param / 100)) * (140) + ((param / 100) ** 3) * (
                    70)
            z = ((1 - (param / 100)) ** 3) * 0 + 3 * (param / 100) * ((1 - (param / 100)) ** 2) * (100) + 3 * (
                    (param / 100) ** 2) * (1 - (param / 100)) * (100) + ((param / 100) ** 3) * (
                    0)
            print(param)
            print("минус")

    pgl.glPopMatrix()


@win.event
def on_text_motion(motion):
    global xRotation, yRotation, INCREMENT
    if motion == key.UP:
        xRotation -= INCREMENT
    elif motion == key.DOWN:
        xRotation += INCREMENT
    elif motion == key.LEFT:
        yRotation -= INCREMENT
    elif motion == key.RIGHT:
        yRotation += INCREMENT


@win.event
def on_key_press(symbol, modifiers):
    global transparant, dist, tr, x, y, z, INCREMENT, zRotation, light, t, start_loop, run_loop
    if symbol == key.T and not transparant:
        transparant = True
    elif symbol == key.T and transparant:
        transparant = False
    elif symbol == key.W:
        x += 2.5
    elif symbol == key.S:
        x -= 2.5
    elif symbol == key.A:
        y -= 2.5
    elif symbol == key.D:
        y += 2.5
    elif symbol == key.Q:
        z -= 2.5
    elif symbol == key.E:
        z += 2.5
    elif symbol == key.L:
        light = not light
    elif symbol == key.Z:
        zRotation += INCREMENT
    elif symbol == key.X:
        zRotation -= INCREMENT
    elif symbol == key.ESCAPE:
        pyglet.app.exit()
    elif symbol == key.P:
        tr += 5
    elif symbol == key.O:
        if tr > 5:
            tr -= 5
    elif symbol == key.SPACE:
        if not run_loop:
            start_loop = True
        else:
            run_loop = False


@win.event
def on_mouse_scroll(x, y, scroll_x, scroll_y):
    global zoom
    if scroll_y < 0:
        zoom += 0.1
    elif scroll_y > 0 and zoom - 0.1 > 0:
        zoom -= 0.1


@win.event
def on_mouse_press(x, y, button, modifiers):
    if button == pyglet.window.mouse.LEFT:
        print(x, y)


pyglet.clock.schedule_interval(run_loop, 0.1)
pyglet.app.run()

编辑:

首先你必须通过pyglet.image.load respectively get_texture():

将纹理图像加载到纹理对象
texture_obj = pyglet.image.load('texture.png').get_texture()

纹理必须由glBindTexture绑定:

pgl.glBindTexture(pgl.GL_TEXTURE_2D, texture_obj.id)

二维纹理由 glEnable(GL_TEXTURE_2D) 启用,可由 glDisable(GL_TEXTURE_2D) 禁用。
如果启用纹理,则应用 glBegin/glEnd 序列绘制几何时当前绑定的纹理:

pgl.glEnable(pgl.GL_TEXTURE_2D)

如果启用纹理,则默认情况下纹理元素的颜色乘以当前颜色,因为默认情况下纹理环境模式 (GL_TEXTURE_ENV_MODE) 为 GL_MODULATE。参见 glTexEnv

这会导致纹理的纹素颜色 "mixed" 是您通过 glColor3ub 设置的最后一种颜色。

在渲染纹理之前设置 "white" 颜色,以解决您的问题:

plg.glColor3ub(255, 255, 255)

pgl.glColor3f(1, 1, 1)

同样,您可以将环境模式更改为 GL_REPLACE,而不是:

pgl.glTexEnvi(pgl.GL_TEXTURE_ENV, pgl.GL_TEXTURE_ENV_MODE, pgl.GL_REPLACE)

glVertex is called, the the current texture coordinates are associated with the vertex coordinate. The texture coordinate is set by glTexCoord2f.
您必须设置与每个顶点坐标对应的纹理坐标。纹理坐标必须在 [0, 1] 范围内。另见 How do opengl texture coordinates work?.

例如

u = math.cos(i * 2 * math.pi / tr)
v = math.sin(i * 2 * math.pi / tr)
pgl.glTexCoord2f(u*0.5+0.5, v*0.5+0.5)
a1 = x + a * u
a2 = y + b * v
a3 = z + 8
pgl.glVertex3f(a1, a2, a3)

函数 draw_figure 可能如下所示。注意,我不完全知道你想如何将纹理包裹到网格上,所以我按照我的想法计算纹理坐标。您可能需要根据需要调整纹理坐标的计算:

texture_obj = None 

def draw_figure():

    global texture_obj

    # [...]

    if texture_obj == None:
        texture_obj = pyglet.image.load('texture.png').get_texture()
    pgl.glBindTexture(pgl.GL_TEXTURE_2D, texture_obj.id)
    pgl.glEnable(pgl.GL_TEXTURE_2D)
    pgl.glTexEnvi(pgl.GL_TEXTURE_ENV, pgl.GL_TEXTURE_ENV_MODE, pgl.GL_REPLACE)

    if not transparant:
        pgl.glPolygonMode(pgl.GL_FRONT_AND_BACK, pgl.GL_FILL)
    else:
        pgl.glPolygonMode(pgl.GL_FRONT_AND_BACK, pgl.GL_LINE)
    pgl.glBegin(pgl.GL_TRIANGLE_STRIP)
    for i in range(0, tr + 1):
        pgl.glColor3ub(255, 255, 255)
        if i >= 1:
            t1 = a1
            t2 = a2
            t3 = a3
        u = math.cos(i * 2 * math.pi / tr)
        v = math.sin(i * 2 * math.pi / tr)
        a1 = x + a * u
        a2 = y + b * v
        a3 = z + 8
        pgl.glTexCoord2f(u*0.5+0.5, v*0.5+0.5)
        pgl.glVertex3f(a1, a2, a3)
        if i >= 1:
            pgl.glNormal3f((b2 - t2) * (a3 - b3) - (b3 - t3) * (a2 - b2), (b3 - t3) * (a1 - b1) - (b1 - t1) * (a3 - b3),
                           (b1 - t1) * (a2 - b2) - (b2 - t2) * (a1 - b1))
        b1 = x
        b2 = y
        b3 = z + 8
        pgl.glTexCoord2f(0.5, 0.5)
        pgl.glVertex3f(b1, b2, b3)
    pgl.glEnd()
    for j in range(1, 27):
        pgl.glBegin(pgl.GL_TRIANGLE_STRIP)
        pgl.glColor3ub(255, 255, 255)
        x1 = a * math.cos(0)
        y1 = b * math.sin(0)
        a1 = x1 * math.cos(t * math.pi / 360) + y1 * math.sin(t * math.pi / 360)
        a2 = - x1 * math.sin(t * math.pi / 360) + y1 * math.cos(t * math.pi / 360)
        a3 = z + j * 8
        pgl.glTexCoord2f(0.0, 0.0)
        pgl.glVertex3f(a1, a2, a3)
        b1 = x1 * math.cos((t + 16) * math.pi / 360) + y1 * math.sin((t + 16) * math.pi / 360)
        b2 = - x1 * math.sin((t + 16) * math.pi / 360) + y1 * math.cos((t + 16) * math.pi / 360)
        b3 = z + j * 8 + 8
        u = math.cos((t + 16) * math.pi / 360) + math.sin((t + 16) * math.pi / 360)
        v = (j-1)/26
        pgl.glTexCoord2f(0.0, 0.0)
        pgl.glVertex3f(b1, b2, b3)
        for i in range(1, tr + 1):
            pgl.glColor3ub(255, 255, 255)
            x1 = a * math.cos(i * 2 * math.pi / tr)
            y1 = b * math.sin(i * 2 * math.pi / tr)
            t1 = a1
            t2 = a2
            t3 = a3
            a1 = x1 * math.cos(t * math.pi / 360) + y1 * math.sin(t * math.pi / 360)
            a2 = - x1 * math.sin(t * math.pi / 360) + y1 * math.cos(t * math.pi / 360)
            a3 = z + j * 8
            pgl.glNormal3f((b2 - t2) * (a3 - b3) - (b3 - t3) * (a2 - b2), (b3 - t3) * (a1 - b1) - (b1 - t1) * (a3 - b3),
                           (b1 - t1) * (a2 - b2) - (b2 - t2) * (a1 - b1))
            v = math.cos(t * math.pi / 360) + math.sin(t * math.pi / 360)
            pgl.glTexCoord2f((i-1)/tr, (26-j)/26)
            pgl.glVertex3f(a1, a2, a3)
            x1 = a * math.cos(i * 2 * math.pi / tr)
            y1 = b * math.sin(i * 2 * math.pi / tr)
            b1 = x1 * math.cos((t + 16) * math.pi / 360) + y1 * math.sin((t + 16) * math.pi / 360)
            b2 = - x1 * math.sin((t + 16) * math.pi / 360) + y1 * math.cos((t + 16) * math.pi / 360)
            b3 = z + j * 8 + 8
            v = math.cos((t + 16) * math.pi / 360) + math.sin((t + 16) * math.pi / 360)
            pgl.glTexCoord2f((i-1)/tr, (25-j)/26)
            pgl.glVertex3f(b1, b2, b3)
        t = t + 16
        pgl.glEnd()
    pgl.glBegin(pgl.GL_TRIANGLE_STRIP)
    t = 416
    z = z + 144
    angle = angle + t
    for i in range(0, tr + 1):
        pgl.glColor3ub(255, 255, 255)
        u = math.cos(i * 2 * math.pi / tr)
        v = math.sin(i * 2 * math.pi / tr)
        x1 = x + a * u
        y1 = y + b * v
        x2 = x1 * math.cos(t * math.pi / 360) + y1 * math.sin(t * math.pi / 360)
        y2 = - x1 * math.sin(t * math.pi / 360) + y1 * math.cos(t * math.pi / 360)
        if i >= 1:
            t1 = a1
            t2 = a2
            t3 = a3
        a1 = x2
        a2 = y2
        a3 = z + 72
        pgl.glTexCoord2f(u*0.5+0.5, v*0.5+0.5)
        pgl.glVertex3f(a1, a2, a3)
        if i >= 1:
            pgl.glNormal3f((b2 - t2) * (a3 - b3) - (b3 - t3) * (a2 - b2), (b3 - t3) * (a1 - b1) - (b1 - t1) * (a3 - b3),
                           (b1 - t1) * (a2 - b2) - (b2 - t2) * (a1 - b1))
        b1 = x
        b2 = y
        b3 = z + 72
        pgl.glTexCoord2f(0.5, 0.5)
        pgl.glVertex3f(b1, b2, b3)
        angle = angle + i
    pgl.glEnd()