Object rotating in an orbit instead of axis

I’ve built a wall and when I call setH on it, instead of the wall rotating on its own axis, it rotates in an orbit. The problem disappears when I build the wall using first point of [0,0] and any for the second point (build([0,0],[1,1]). That’s the furthest I was able to diagnose the problem.

from panda3d.core import *
from direct.showbase.ShowBase import ShowBase
from direct.gui.DirectGui import *
import math

class Core(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        self.cam.setP(-90)
        self.cam.setPos(0, 0, 45)

        wall = self.build([-3,1],[-1,1])
        def change():
            wall.setH(slider['value'])
        slider = DirectSlider(range=(0, 360), pos=(0, 0, -0.5), value=0, command=change)

    def makeSquare(self,x1, y1, z1, x2, y2, z2):
        format = GeomVertexFormat.getV3n3cpt2()
        vdata = GeomVertexData('square', format, Geom.UHDynamic)

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

        if x1 != x2:
            vertex.addData3f(x1, y1, z1)
            vertex.addData3f(x2, y1, z1)
            vertex.addData3f(x2, y2, z2)
            vertex.addData3f(x1, y2, z2)

            normal.addData3f(Vec3(2 * x1 - 1, 2 * y1 - 1, 2 * z1 - 1))
            normal.addData3f(Vec3(2 * x2 - 1, 2 * y1 - 1, 2 * z1 - 1))
            normal.addData3f(Vec3(2 * x2 - 1, 2 * y2 - 1, 2 * z2 - 1))
            normal.addData3f(Vec3(2 * x1 - 1, 2 * y2 - 1, 2 * z2 - 1))

        else:
            vertex.addData3f(x1, y1, z1)
            vertex.addData3f(x2, y2, z1)
            vertex.addData3f(x2, y2, z2)
            vertex.addData3f(x1, y1, z2)

            normal.addData3f(Vec3(2 * x1 - 1, 2 * y1 - 1, 2 * z1 - 1))
            normal.addData3f(Vec3(2 * x2 - 1, 2 * y2 - 1, 2 * z1 - 1))
            normal.addData3f(Vec3(2 * x2 - 1, 2 * y2 - 1, 2 * z2 - 1))
            normal.addData3f(Vec3(2 * x1 - 1, 2 * y1 - 1, 2 * z2 - 1))

        color.addData4f(1.0, 1.0, 1.0, 1.0)

        texcoord.addData2f(0.0, 1.0)
        texcoord.addData2f(0.0, 0.0)
        texcoord.addData2f(1.0, 0.0)
        texcoord.addData2f(1.0, 1.0)

        tri1 = GeomTriangles(Geom.UHDynamic)
        tri2 = GeomTriangles(Geom.UHDynamic)

        tri1.addVertex(0)
        tri1.addVertex(1)
        tri1.addVertex(3)

        tri2.addConsecutiveVertices(1, 3)

        tri1.closePrimitive()
        tri2.closePrimitive()

        square = Geom(vdata)
        square.addPrimitive(tri1)
        square.addPrimitive(tri2)

        return square
    def build(self,pt1, pt2=[]):
        cs = 0.2
        if pt1[1] == pt2[1]:
            # wall is left right
            if pt1[0] - pt2[0] < 0:
                p1, p2 = pt1, pt2
                pt1 = p2
                pt2 = p1
            main1pt = [pt1[0], pt1[1] - cs / 2, 0]
            main1pt1 = [pt2[0], pt2[1] + cs / 2, 0]
            main1pt2 = [pt1[0], pt1[1] + cs / 2, 3]
            main1pt3 = [pt2[0], pt2[1] - cs / 2, 3]

            main2pt = [pt2[0], pt2[1] + cs / 2, 3]
            main2pt1 = [pt1[0], pt1[1] - cs / 2, 3]
            main2pt2 = [pt2[0], pt2[1] - cs / 2, 0]
            main2pt3 = [pt1[0], pt1[1] + cs / 2, 0]

        if pt1[0] == pt2[0]:
            # wall is up down
            main1pt = [pt1[0] - cs / 2, pt1[1], 0]
            main1pt1 = [pt2[0] + cs / 2, pt2[1], 0]
            main1pt2 = [pt1[0] + cs / 2, pt1[1], 3]
            main1pt3 = [pt2[0] - cs / 2, pt2[1], 3]

            main2pt = [pt2[0] + cs / 2, pt2[1], 3]
            main2pt1 = [pt1[0] - cs / 2, pt1[1], 3]
            main2pt2 = [pt2[0] - cs / 2, pt2[1], 0]
            main2pt3 = [pt1[0] + cs / 2, pt1[1], 0]

        else:
            rotated = True
            xdiff = pt1[0] - pt2[0]
            ydiff = pt1[1] - pt2[1]
            newx = pt1[0] - math.sqrt(abs(xdiff) ** 2 + abs(ydiff) ** 2)
            angle = math.degrees(math.atan(ydiff / xdiff))
            main1pt = [pt1[0], pt1[1] - cs / 2, 0]
            main1pt1 = [newx, pt1[1] + cs / 2, 0]
            main1pt2 = [pt1[0], pt1[1] + cs / 2, 3]
            main1pt3 = [newx, pt1[1] - cs / 2, 3]

            main2pt = [newx, pt1[1] + cs / 2, 3]
            main2pt1 = [pt1[0], pt1[1] - cs / 2, 3]
            main2pt2 = [newx, pt1[1] - cs / 2, 0]
            main2pt3 = [pt1[0], pt1[1] + cs / 2, 0]

        square0 = self.makeSquare(*(main1pt + main1pt1))
        square1 = self.makeSquare(*(main1pt + main1pt2))
        square2 = self.makeSquare(*(main1pt + main1pt3))
        square3 = self.makeSquare(*(main2pt + main2pt1))
        square4 = self.makeSquare(*(main2pt + main2pt2))
        square5 = self.makeSquare(*(main2pt + main2pt3))

        snode = GeomNode('')
        snode.addGeom(square0)
        snode.addGeom(square1)
        snode.addGeom(square2)
        snode.addGeom(square3)
        snode.addGeom(square4)
        snode.addGeom(square5)
        cube = render.attachNewNode(snode)
        cube.setTwoSided(True)
        cube.setColor(1,0,0,1)
        return cube

core = Core()
core.run()

I understand from previous posts that I need to reset the origin of the object as it is always at world 0,0

Using [0,0] as in build([0,0],[-1,1]) does not seem to fix the issue for me. To me it seems to be the case that the object rotates round the center when you create it using the values

build([(b-a)/2,0],[a,b])

E.g:

build([1,0],[-1,1])

The issue most probably arises because you haven’t set the center/pivot of your wall, and I am a bit unsure on how this is done. However there is another quick fix you may use, and that is you first build your cube/wall as if it was set to be build([(b-a)/2,0],[a,b]) but then setting the position using setPos(…) to what the user actually specifies in the first point.

It seems that the center on which it rotates has nothing to do with the values inputted. No matter what the values are, rotation is always around 0,0.

I agree with this, I haven’t set the center of the wall anywhere and because of that, it seems that it’s set automatically to the world center (0,0).
Ps: calling setPos changes the entire location of the object as expected instead of just the center/pivot point

I may have misunderstood what you are trying to do. But if you want to be able to rotate your procedural cube from its center regardless of where it is positioned in the world, then initially creating the object such that its center lies at the origin (which is where the pivot happens to be) and then moving both the entire location of the object (including the pivot) to wherever you want should work just fine. The only difference is that instead of setting any of the user-defined positions when you create the object, you set them right after.

As a side note that I forgot to mention, the center of your cube node is in fact the actual pivotal point (since you call setH(…) on the cube). You can easily see that by leaving the position of cube undefined, doing cube = render.attachNewNode(snode) has no effect at all for the center of the cube node which you can verify by doing print(cube.getPos()). It always returns (0,0,0) unless cube.setPos(…) is actually used.

Hmm I see what you’re saying and I think you’re right. I changed the way build() works as you suggested. It now makes a cube at 0,0 using the given sizes then its position is set according to the first set of values passed. Cube now rotates around itself!
Thank you for your help :smiley:

Glad to have helped!