【问题标题】:Texture the 3D figure (cylinder)纹理 3D 图形(圆柱体)
【发布时间】:2019-09-22 21:29:45
【问题描述】:

我需要纹理我的圆柱体,我有 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()

编辑:

【问题讨论】:

    标签: python opengl pyglet texturing opengl-compat


    【解决方案1】:

    首先你必须通过pyglet.image.load分别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

    这会导致纹理纹素的颜色与您在glColor3ub 设置的最后一种颜色“混合”。

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

    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被调用时,当前纹理坐标与顶点坐标相关联。纹理坐标由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()
    

    【讨论】:

    • 你的帮助真的很棒,但是我遇到了一些纹理问题,我添加了截图。是因为图像还是我必须在坐标中修复一些东西?
    • @PopeyeTheSailor 我改进了纹理坐标计算并添加了一个 GIF,它显示了我的测试应用程序的结果。
    • 你能把你用来做纹理的图片放下吗?
    • @PopeyeTheSailor 我没有使用 PNG,我使用了 BMP:test1_texture.bmp。在 pyglet 文档中有一个关于加载图像的主题Loading an image。我注意到以下 PNG 也可以:Gominolas.png
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多