I’ve found something that correctly places the wheels, however it poses more questions than answers.
For some reason, copying the code from the class, and into the window’s init function, then replacing the arguments that was passed into the class with the exact same values that they were holding fixes the issue.
however, even after doing this, going back to the class that holds the same arguments as the ones being used in the init version brings it back.
Am i missing something here? Also, here is the code that creates the car in init (noting that the variables used to hold the steeringClamp for example is still using the same arguments, just stated earlier inside it.
self.hitbox_shape = BulletBoxShape(Vec3(1, 2.2, 0.55))
self.ts = TransformState.makePos(Point3(0, 0, 0.75))
self.chassisNP = render.attachNewNode(BulletRigidBodyNode("Car"))
self.chassisNP.node().addShape(self.hitbox_shape, self.ts)
self.chassisNP.setPos(0, 0, 0)
self.chassisNP.node().setMass(1520)
self.chassisNP.node().setDeactivationEnabled(False)
self.world.attachRigidBody(self.chassisNP.node())
# Chassis geometry
loader.loadModel(globals.rel_path(None, path="/src/models/cars/Supra Body ReScale rotate Nglass.bam")).reparentTo(
self.chassisNP)
# Vehicle
self.vehicle = BulletVehicle(self.world, self.chassisNP.node())
self.vehicle.setCoordinateSystem(ZUp)
self.world.attachVehicle(self.vehicle)
globals.carObjects.append(self.vehicle)
self.LFwheelNP = loader.loadModel(globals.rel_path(None, "/src/models/cars/Supra Wheel L RS.bam"))
self.LFwheelNP.reparentTo(render)
self.RFwheelNP = loader.loadModel(globals.rel_path(None, "/src/models/cars/Supra Wheel R RS.bam"))
self.RFwheelNP.reparentTo(render)
self.LBwheelNP = loader.loadModel(globals.rel_path(None, "/src/models/cars/Supra Wheel L RS.bam"))
self.LBwheelNP.reparentTo(render)
self.RBwheelNP = loader.loadModel(globals.rel_path(None, "/src/models/cars/Supra Wheel R RS.bam"))
self.RBwheelNP.reparentTo(render)
front_wheel_distance = (0.9, 1.35, 0.65)
rear_wheel_distance = (0.9, 1.25, 0.65)
#
# self.LFwheel = self.addWheel(Point3(0.9, 1.35, 0.65), True, self.LFwheelNP)
# self.RFwheel = self.addWheel(Point3(-0.9, 1.35, 0.65), True, self.RFwheelNP)
# self.LBwheel = self.addWheel(Point3(0.9, -1.25, 0.65), False, self.LBwheelNP)
# self.RBwheel = self.addWheel(Point3(-0.9, -1.25, 0.65), False, self.RBwheelNP)
self.LFwheel = self.addWheel(Point3(front_wheel_distance[0], front_wheel_distance[1], front_wheel_distance[2]), True, self.LFwheelNP)
self.RFwheel = self.addWheel(Point3(-front_wheel_distance[0], front_wheel_distance[1], front_wheel_distance[2]), True, self.RFwheelNP)
self.LBwheel = self.addWheel(Point3(rear_wheel_distance[0], -rear_wheel_distance[1], rear_wheel_distance[2]), False, self.LBwheelNP)
self.RBwheel = self.addWheel(Point3(-rear_wheel_distance[0], -rear_wheel_distance[1], rear_wheel_distance[2]), False, self.RBwheelNP)
Full window class (It does contain the same code for making the car, However it means if I’m missing something it should be easier to see.
The version that uses the seperate class is still the current version for the repository in cases of comparison.
class MainWindow(ShowBase):
def doExit(self):
# os.system('xset r on')
sys.exit(1)
def rel_path(self, path="/src"):
# Get the location of the 'py' file I'm running:
dir = os.path.abspath(sys.path[0])
# Convert that to panda's unix-style notation.
dir = Filename.fromOsSpecific(dir).getFullpath()
return dir + path
# Macro-like function to reduce the amount of code needed to create the
# onscreen instructions
def makeStatusLabel(self, i):
return OnscreenText(
parent=base.a2dTopLeft, align=TextNode.ALeft,
style=1, fg=(1, 1, 0, 1), shadow=(0, 0, 0, .4),
pos=(0.06, -0.1 -(.06 * i)), scale=.05, mayChange=True)
def convZUp(self, x, y, z):
return (x, -z, y)
# def camera_task(self, *args, **kwargs):
# current_steer = globals.carObjects[0].steering
# xcoord = None
# base.cam.setPos(5, -8, 2.1)
# base.cam.lookAt(0, 0, 0.3)
def addWheel(self, pos, isfrontwheel, np):
wheel = self.vehicle.createWheel()
wheel.setNode(np.node())
wheel.setChassisConnectionPointCs(pos)
wheel.setFrontWheel(isfrontwheel)
wheel.setWheelDirectionCs(Vec3(0, 0, -1))
wheel.setWheelAxleCs(Vec3(1, 0, 0))
wheel.setWheelRadius(0.25)
wheel.setMaxSuspensionTravelCm(10.0)
wheel.setSuspensionStiffness(40.0)
wheel.setWheelsDampingRelaxation(2.3)
wheel.setWheelsDampingCompression(4.4)
wheel.setFrictionSlip(8.0)
wheel.setRollInfluence(0.1)
def accelerate(self):
self.vehicle.applyEngineForce(5000, 2)
self.vehicle.applyEngineForce(5000, 3)
def reverse(self):
self.vehicle.applyEngineForce(-1000, 2)
self.vehicle.applyEngineForce(-1000, 3)
def noaccelerate(self):
self.vehicle.applyEngineForce(0, 2)
self.vehicle.applyEngineForce(0, 3)
# self.vehicle.(0, 0)
def brake(self):
self.vehicle.setBrake(100, 0)
self.vehicle.setBrake(100, 1)
self.vehicle.setBrake(100, 2)
self.vehicle.setBrake(100, 3)
def nobrake(self):
self.vehicle.setBrake(0, 0)
self.vehicle.setBrake(0, 1)
self.vehicle.setBrake(0, 2)
self.vehicle.setBrake(0, 3)
def turnleft(self):
self.nosteerinput = False
self.steering += globalClock.getDt() * self.steeringIncrement
self.steering = min(self.steering, self.steeringClamp)
self.vehicle.setSteeringValue(self.steering, 0)
self.vehicle.setSteeringValue(self.steering, 1)
def nosteermethod(self, *args, **kwargs):
self.nosteerinput = True
def noturn(self):
if self.steering < 0:
self.steering += globalClock.getDt() * self.steeringIncrement
self.steering = min(self.steering, self.steeringClamp)
elif self.steering > 0:
self.steering -= globalClock.getDt() * self.steeringIncrement
self.steering = max(self.steering, -self.steeringClamp)
if (self.steering >= -0.1 and self.steering < 0) or (self.steering <= 0.1 and self.steering > 0):
self.steering = 0
self.vehicle.setSteeringValue(self.steering, 0)
self.vehicle.setSteeringValue(self.steering, 1)
def turnright(self):
self.nosteerinput = False
self.steering -= globalClock.getDt() * self.steeringIncrement
self.steering = max(self.steering, -self.steeringClamp)
self.vehicle.setSteeringValue(self.steering, 0)
self.vehicle.setSteeringValue(self.steering, 1)
def move_task(self, *args, **kwargs):
# speed = 0.0
if self.keymonitor(self.forward_button):
self.accelerate()
# if is_down(self.reverse_button): # seems to disallow forward engine force when reverse engine force is used
# self.reverse()
else:
self.noaccelerate()
if self.keymonitor(self.brake_button):
self.brake()
else:
self.nobrake()
if self.keymonitor(self.left_button):
self.turnleft()
if self.keymonitor(self.right_button):
self.turnright()
if not(self.keymonitor(self.left_button)) and not(self.keymonitor(self.right_button)):
self.nosteerinput = True
if self.nosteerinput:
self.noturn()
def reverse_task(self, *args, **kwargs):
if self.keymonitor(self.reverse_button): # seems to disallow forward engine force when reverse engine force is used
self.reverse()
def hud_task(self, *args, **kwargs):
# kph_measure = globals.carObjects[0].vehicle.getCurrentSpeedKmHour()
kph_measure = 10
self.speedometer_kph.setText("Speed (kph): " + str(round(kph_measure, 1)))
self.speedometer_mph.setText("Speed (mph): " + str(round(mph_measure := (kph_measure * 0.6213712), 1)))
# def updateStatusLabel(self, *args, **kwargs):
def update(self, task):
dt = globalClock.getDt()
self.world.doPhysics(dt, 10, 0.008)
# if self.nosteerinput:
# self.noturn()
self.move_task()
self.reverse_task()
# for i in globals.carObjects:
# i.move_task()
# i.reverse_task()
# self.camera_task()
self.hud_task()
return task.cont
def __init__(self):
# Initialize the ShowBase class from which we inherit, which will
# create a window and set up everything we need for rendering into it.
ShowBase.__init__(self)
self.keymonitor = base.mouseWatcherNode.is_button_down
dir_path = Path(sys.path[0])
self.use_kph = True
# self.is_down = base.mouseWatcherNode.is_button_down
self.forward_button = KeyboardButton.ascii_key('w') # 'raw-' prefix is being used to mantain WASD positioning on other keyboard layouts
self.left_button = KeyboardButton.ascii_key('a')
self.brake_button = KeyboardButton.ascii_key('s')
self.right_button = KeyboardButton.ascii_key('d')
self.reverse_button = KeyboardButton.ascii_key('r')
self.speedometer_kph = self.makeStatusLabel(0)
self.speedometer_mph = self.makeStatusLabel(1)
# Plane
self.worldNP = render.attachNewNode('World')
shape = BulletPlaneShape(Vec3(0, 0, 1), 0)
np = self.worldNP.attachNewNode(BulletRigidBodyNode('Ground'))
np.node().addShape(shape)
np.setPos(0, 0, -1)
# np.setCollideMask(BitMask32.allOn())
# Steering info
self.steering = 0.0 # degrees
self.steeringClamp = 40.0 # degrees
self.steeringIncrement = 100.0 # degrees per second
self.nosteerinput = False
base.cam.setPos(0, -8, 2.1)
base.cam.lookAt(0, 0, 0.3)
# Directional light 02
directionalLight = DirectionalLight('directionalLight')
directionalLight.setColorTemperature(6250)
# directionalLight.setColor((0.2, 0.2, 0.8, 1))
directionalLightNP = render.attachNewNode(directionalLight)
# This light is facing forwards, away from the camera.
directionalLightNP.setHpr(0, -20, 0)
render.setLight(directionalLightNP)
self.lowPassFilter = AlphaTestAttrib.make(TransparencyAttrib.MDual, 0.5)
self.debugNP = self.worldNP.attachNewNode(BulletDebugNode('Debug'))
self.debugNP.show()
self.world = BulletWorld()
self.world.setDebugNode(self.debugNP.node())
self.world.attachRigidBody(np.node())
self.world.setGravity(Vec3(0, 0, -9.81))
# self.test_car = BulletCar(world=self.world, keymonitor=self.keymonitor,
# forward_button=self.forward_button, left_button=self.left_button,
# right_button=self.right_button, brake_button=self.brake_button,
# reverse_button=self.reverse_button)
# base.cam.reparentTo(self.test_car.chassisNP) # Use this line to make the camera follow the car
self.forward_button = forward_button
self.left_button = left_button
self.right_button = right_button
self.brake_button = brake_button
self.reverse_button = reverse_button)
self.hitbox_shape = BulletBoxShape(Vec3(1, 2.2, 0.55))
self.ts = TransformState.makePos(Point3(0, 0, 0.75))
self.chassisNP = render.attachNewNode(BulletRigidBodyNode("Car"))
self.chassisNP.node().addShape(self.hitbox_shape, self.ts)
self.chassisNP.setPos(0, 0, 0)
self.chassisNP.node().setMass(1520)
self.chassisNP.node().setDeactivationEnabled(False)
self.world.attachRigidBody(self.chassisNP.node())
# Chassis geometry
loader.loadModel(globals.rel_path(None, path="/src/models/cars/Supra Body ReScale rotate Nglass.bam")).reparentTo(
self.chassisNP)
# Vehicle
self.vehicle = BulletVehicle(self.world, self.chassisNP.node())
self.vehicle.setCoordinateSystem(ZUp)
self.world.attachVehicle(self.vehicle)
globals.carObjects.append(self.vehicle)
self.LFwheelNP = loader.loadModel(globals.rel_path(None, "/src/models/cars/Supra Wheel L RS.bam"))
self.LFwheelNP.reparentTo(render)
self.RFwheelNP = loader.loadModel(globals.rel_path(None, "/src/models/cars/Supra Wheel R RS.bam"))
self.RFwheelNP.reparentTo(render)
self.LBwheelNP = loader.loadModel(globals.rel_path(None, "/src/models/cars/Supra Wheel L RS.bam"))
self.LBwheelNP.reparentTo(render)
self.RBwheelNP = loader.loadModel(globals.rel_path(None, "/src/models/cars/Supra Wheel R RS.bam"))
self.RBwheelNP.reparentTo(render)
front_wheel_distance = (0.9, 1.35, 0.65)
rear_wheel_distance = (0.9, 1.25, 0.65)
#
# self.LFwheel = self.addWheel(Point3(0.9, 1.35, 0.65), True, self.LFwheelNP)
# self.RFwheel = self.addWheel(Point3(-0.9, 1.35, 0.65), True, self.RFwheelNP)
# self.LBwheel = self.addWheel(Point3(0.9, -1.25, 0.65), False, self.LBwheelNP)
# self.RBwheel = self.addWheel(Point3(-0.9, -1.25, 0.65), False, self.RBwheelNP)
self.LFwheel = self.addWheel(Point3(front_wheel_distance[0], front_wheel_distance[1], front_wheel_distance[2]), True, self.LFwheelNP)
self.RFwheel = self.addWheel(Point3(-front_wheel_distance[0], front_wheel_distance[1], front_wheel_distance[2]), True, self.RFwheelNP)
self.LBwheel = self.addWheel(Point3(rear_wheel_distance[0], -rear_wheel_distance[1], rear_wheel_distance[2]), False, self.LBwheelNP)
self.RBwheel = self.addWheel(Point3(-rear_wheel_distance[0], -rear_wheel_distance[1], rear_wheel_distance[2]), False, self.RBwheelNP)
## TODO: coord system - xpositive = right, ypositive = back, zpositive = up
map = base.win.get_keyboard_map()
# Use this to print all key mappings
print(map)
# Find out which virtual key is associated with the ANSI US "w"
w_button = map.get_mapped_button("w")
# Use a 512x512 resolution shadow map
directionalLight.setShadowCaster(True, 512, 512)
# Enable the shader generator for the receiving nodes
render.setShaderAuto()
# Update
taskMgr.add(self.update, 'update')
# taskMgr.add(self.move_task, 'inputmanager')
if __name__ == '__main__':
# Make an instance of our class and run the demo
app = MainWindow()
app.run()