Creating a simple Cube model

I’m building a game that will be mostly algorithmically generated. Think 3D Tetris with more complex blocks. My basic building elements are, of course, cubes. So here’s what I want: a model which is a cube, moderate shininess, moderate reflectivity, one of several colors. No texture required.

Now, can I generate that within panda 3D itself, or do I need to go off and learn blender to create my basic cubes? A pointer to a good tutorial would be great.

(After mastering that, I might try a cube with slightly rounded edges.)

You can procedurally generate the geometry, then procedurally create the material.

https://docs.panda3d.org/1.10/python/programming/internal-structures/procedural-generation/index#procedurally-generating-3d-models

https://docs.panda3d.org/1.10/python/programming/render-attributes/materials#materials

from panda3d.core import GeomVertexData, GeomVertexFormat, Geom, GeomTriangles, GeomVertexWriter, GeomNode, Texture, TextureAttrib, NodePath, RenderState, ModelRoot
from direct.showbase.ShowBase import ShowBase

class MyApp(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)

        # Creating vertex data.
        vdata = GeomVertexData('name', GeomVertexFormat.getV3n3t2(), Geom.UHStatic)
        vdata.setNumRows(3)

        vertex = GeomVertexWriter(vdata, 'vertex')
        normal = GeomVertexWriter(vdata, 'normal')
        texcoord = GeomVertexWriter(vdata, 'texcoord')

        # Adding vertex data.
        vertex.addData3(-1, -1, 0)
        vertex.addData3(1, -1, 0)
        vertex.addData3(1, 1, 0)
        vertex.addData3(-1, 1, 0)

        normal.addData3(0, 0, 1)
        normal.addData3(0, 0, 1)
        normal.addData3(0, 0, 1)
        normal.addData3(0, 0, 1)
        
        texcoord.addData2(0, 0)
        texcoord.addData2(1, 0)
        texcoord.addData2(1, 1)
        texcoord.addData2(0, 1)


        # Creating primitive - a.
        prim_a = GeomTriangles(Geom.UHStatic)
        prim_a.addVertices(0, 1, 2)
        prim_a.addVertices(0, 2, 3)
        prim_a.closePrimitive()

        geom1 = Geom(vdata)
        geom1.addPrimitive(prim_a)


        # Load texture.
        tex1 = Texture("Texture")
        tex1.setup2dTexture()
        tex1.read('panda.jpg')
        tex1.setMagfilter(Texture.FTNearest)
        tex1.setMinfilter(Texture.FTNearest)

        # Create new geom state.
        state_a = RenderState.make(TextureAttrib.make(tex1))

        # Create geom node.
        geom_node = GeomNode('Plane')
        geom_node.add_geom(geom1, state_a)

        # Attach geom node.
        root = NodePath(geom_node)
        root.reparent_to(render)
        #root.writeBamFile("plane.bam")

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

Wow, thanks for the detailed example! So it looks like I really do need to load an external texture file to set the material properties of the surface. (Reflectance, too?) It’s not like Unity where you can just build a Material from raw attributes. True?

Here is an example with the material, but panda3d has a limited shader generator. It doesn’t even generate glare when the normal map is applied.

from panda3d.core import (GeomVertexData, GeomVertexFormat, Geom, GeomTriangles, GeomVertexWriter, 
GeomNode, Texture, TextureAttrib, NodePath, RenderState, Material, MaterialAttrib, DirectionalLight)
from direct.showbase.ShowBase import ShowBase

class MyApp(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)

        # Creating vertex data.
        vdata = GeomVertexData('name', GeomVertexFormat.getV3n3t2(), Geom.UHStatic)
        vdata.setNumRows(3)

        vertex = GeomVertexWriter(vdata, 'vertex')
        normal = GeomVertexWriter(vdata, 'normal')
        texcoord = GeomVertexWriter(vdata, 'texcoord')

        # Adding vertex data.
        vertex.addData3(-1, -1, 0)
        vertex.addData3(1, -1, 0)
        vertex.addData3(1, 1, 0)
        vertex.addData3(-1, 1, 0)

        normal.addData3(0, 0, 1)
        normal.addData3(0, 0, 1)
        normal.addData3(0, 0, 1)
        normal.addData3(0, 0, 1)
        
        texcoord.addData2(0, 0)
        texcoord.addData2(1, 0)
        texcoord.addData2(1, 1)
        texcoord.addData2(0, 1)


        # Creating primitive - a.
        prim_a = GeomTriangles(Geom.UHStatic)
        prim_a.addVertices(0, 1, 2)
        prim_a.addVertices(0, 2, 3)
        prim_a.closePrimitive()

        geom1 = Geom(vdata)
        geom1.addPrimitive(prim_a)

        # Load texture.
        tex1 = Texture("Texture")
        tex1.setup2dTexture()
        tex1.read('panda.jpg')
        tex1.setMagfilter(Texture.FTNearest)
        tex1.setMinfilter(Texture.FTNearest)

        # Create new material.
        mat = Material("Material1")
        mat.set_shininess(5.0)
        mat.set_base_color((0, 1, 0, 1))

        # Create new geom state.
        state_a = RenderState.make(TextureAttrib.make(tex1), MaterialAttrib.make(mat))

        # Create geom node.
        geom_node = GeomNode('Plane')
        geom_node.add_geom(geom1, state_a)

        # Attach geom node.
        root = NodePath(geom_node)
        root.reparent_to(render)
        
        # Create light.
        slight = DirectionalLight('slight')
        slight.getLens().set_film_size(10)
        slight.getLens().set_near_far(0.1, 17)
        slight.set_color((1,1,1,1))
        slight.show_frustum()
        #slight.set_shadow_caster(True, 1024, 1024)

        np_slight = NodePath(slight)
        np_slight.set_z(10)
        np_slight.set_p(-90)
        np_slight.reparent_to(render)

        render.set_light(np_slight)
        
        render.set_shader_auto()

        #root.writeBamFile("plane.bam")

app = MyApp()
app.run()

But you can use a static map for this.

https://docs.panda3d.org/1.10/python/programming/texturing/simple-environment-mapping#simple-environment-mapping

At the same time, you need to familiarize yourself with the principles of rendering in panda, or write your own based on shaders.

Following this lesson, I wrote my own pipeline, now it remains to finish writing a plugin for the blender…

You can take a look at the project: GitHub - Moguri/panda3d-simplepbr: A straight-forward, easy-to-use, drop-in, PBR replacement for Panda3D's builtin auto shader
Perhaps this will suit you.

You might also take a look at complexpbr–which, despite the name, is not all that complex to use I think–an alternative project to simplepbr, above.

You can skip the texture in the above example (textures are not required) and just use the Material/MaterialAttrib.