Can I create a flat-shaded cube using only 8 vertices?

Yeah, that example could use some improvement I guess. (@rdb perhaps, if I have some time, I might volunteer to make it a bit more up-to-date, e.g. using snake_case method names, replacing addDataxf with add_datax (especially removing the “f” at the end, now that I know why this is important :wink: ), and perhaps even adding memoryview into the mix as an advanced alternative for GeomVertexWriter?)

So if, like me, you prefer a more “compact” creation code, the following might be to your liking (I’ve included procedural generation of normals, vertex colours and texture coordinates as well):

from panda3d.core import *
from direct.showbase.ShowBase import ShowBase


def create_cube(parent):

    vertex_format = GeomVertexFormat.get_v3n3c4t2()
    vertex_data = GeomVertexData("cube_data", vertex_format, Geom.UH_static)
    tris_prim = GeomTriangles(Geom.UH_static)

    pos_writer = GeomVertexWriter(vertex_data, "vertex")
    normal_writer = GeomVertexWriter(vertex_data, "normal")
    color_writer = GeomVertexWriter(vertex_data, "color")
    uv_writer = GeomVertexWriter(vertex_data, "texcoord")

    vertex_count = 0
    # (left=purple, back=green, down=blue, right=red, front=yellow, up=white)
    colors = ((1., 0., 1.), (0., 1., 0.), (0., 0., 1.),
              (1., 0., 0.), (1., 1., 0.), (1., 1., 1.))

    for direction in (-1, 1):

        for i in range(3):

            normal = VBase3()
            normal[i] = direction
            r, g, b = colors[i if direction == -1 else i-3]
            color = (r, g, b, 1.)

            for a, b in ((-1., -1.), (-1., 1.), (1., 1.), (1., -1.)):

                pos = Point3()
                pos[i] = direction
                pos[(i + direction) % 3] = a
                pos[(i + direction * 2) % 3] = b
                uv = (max(0., a), max(0., b))

                pos_writer.add_data3(pos)
                normal_writer.add_data3(normal)
                color_writer.add_data4(color)
                uv_writer.add_data2(uv)

            vertex_count += 4

            tris_prim.add_vertices(vertex_count - 2, vertex_count - 3, vertex_count - 4)
            tris_prim.add_vertices(vertex_count - 4, vertex_count - 1, vertex_count - 2)

    geom = Geom(vertex_data)
    geom.add_primitive(tris_prim)
    node = GeomNode("cube_node")
    node.add_geom(geom)
    cube = parent.attach_new_node(node)

    return cube


class MyApp(ShowBase):

    def __init__(self):

        ShowBase.__init__(self)

        # set up a light source
        p_light = PointLight("point_light")
        p_light.set_color((1., 1., 1., 1.))
        self.light = self.camera.attach_new_node(p_light)
        self.light.set_pos(5., -10., 7.)
        self.render.set_light(self.light)

        # create a cube parented to the scene root
        self.cube = create_cube(self.render)
#        tex = self.loader.load_texture("my_tex.png")
#        self.cube.set_texture(tex)


app = MyApp()
app.run()
1 Like