Problem with rotation - pls HELP

Hi,
I have a (big) problem with object rotation and I hope that there is someone able to help me.

so what am I trying to do : I’m trying to do a game -> you’re sitting in a bunker and shooting incomming enemies. I have camera controlled with mouse and I’m not able to figure out how to rotate a gun model together WITH the camera, so when I rotate camera for examle to the left side the gun rotates with camera left ( but is still a few unites in front of it of course).

Here is the code what I have so far. I am a complete Panda 3d newbie so ANY comments to this source code will surely help me.

(bullet is model of bullet (sphere) - it will be replaced with gun model made in 3d St. MAX later)

THANK YOU FOR YOUR TIME - I HOPE THAT SOMEONE HELPS ME



import direct.directbase.DirectStart
from direct.task import Task
from direct.actor import Actor
from pandac.PandaModules import *
from direct.gui.DirectGui import *
from direct.interval.IntervalGlobal import *
from random import random
import math



class world(DirectObject):

 

 def __init__(self):

   self.x=0.5
   self.y=0.5
   self.z=0.5

   self.angle=0
   self.pan=0
   base.disableMouse()

   self.environ = loader.loadModel("models/testbox")
   self.environ.reparentTo(render)
   self.environ.setScale(10,10,10)
   self.environ.setPos(-8,42,0)
   
   self.bullet = loader.loadModel("models/bulletmodel")
   self.bullet.reparentTo(render)
   self.bullet.setScale(0.05,0.05,0.05)
   
   
   self.accept("escape", sys.exit)


   taskMgr.add(self.MouseTask, "MouseTask")
   taskMgr.add(self.BulletMoveTask, "BulletMoveTask")



 def MouseTask(self, task):

      if base.mouseWatcherNode.hasMouse():
  
  	  mpos = base.mouseWatcherNode.getMouse()
	  camera.setPos(0,0,58)

	  if mpos.getX()>.05 and mpos.getX()<1:
                   self.angle -= .15

	  if mpos.getX()<-.05 and mpos.getX()>-1:
		   self.angle += .15

	  if mpos.getY()>.05 and mpos.getY()<1:
		   self.pan += .15

	  if mpos.getY()<-.05 and mpos.getY()>-1:
                 self.pan -= .15
	  camera.setHpr(self.angle, self.pan, 0)


          
      return Task.cont


 def BulletMoveTask(self, task):

      
 angleradians = self.angle * (math.pi / 180.0)        
 self.bullet.setPos(2*math.cos(angleradians),2*math.sin(angleradians),58)
      
 return Task.cont
      

w = world()
run()



Let’s say you have a 3D model of an arm holding a gun. Let’s say, hypothetically, that only the hand and forearm are visible - the elbow is behind the camera. I would put the elbow at the origin.

One thing you could do is actually attach the arm to the camera itself.

self.gun= loader.loadModel(“models/arm-plus-gun”)
self.gun.reparentTo(camera) // LOOK HERE!
self.gun.setPos(0,0,-3) // About 3 feet below the camera

The other thing you could do is not attach them, but just move the arm and camera together:

self.gun= loader.loadModel(“models/arm-plus-gun”)
self.gun.reparentTo(render)

 camera.setPos(0,0,58) 
 self.gun.setPos(0,0,58)

 camera.setHpr(self.angle, self.pan, 0) 
 self.gun.setHpr(self.angle, self.pan, 0) 

Whichever seems more natural to you.

  • Josh

ok thanks and one more (very important) thing :

How do I calculate the exact point from which the bullet should be fired - the end of a gun ? and then when - let’s say - I want the bullet to fly just straight I add for example to x and y position of the bullet 0.2 in every frame (every task.time) ?

Good question. I think the first thing you need to ask yourself is, do you really want to render a bullet? Most shooters that I’ve seen don’t. Unless it’s a slow-moving bullet or a laser, I wouldn’t.

Also - do you want the bullet to go in the direction that the gun is pointing, or do you want it to move toward the crosshairs in the middle of the screen? I think it could be very annoying to not go where the crosshairs are aiming. I’d use that, not the direction the gun is pointing.

That said, here’s what you can do. Put a Maya bone or a Max joint in the end of the gun, pointing down the barrel. Use the function ‘exposeJoint’ to fetch a handle to the joint, then you can fetch the position and orientation:

self.gunBarrel = self.gun.exposeJoint(…)
pos = self.gunBarrel.getPos()

The documentation for exposejoint is here:

panda3d.org/manual/index.php/Attac … to_a_Joint

thanks again - this is very interesting idea :bulb:
I woudn’t figure it out myself… :exclamation:

Another way to go about solving the problem (very similar to what Josh suggested) is to use a Maya Locator ( or the Max equivalent ) in place of a joint. For instance:

# Load the gun model and position it accordingly with respect to the
# camera.
self.gunModel = loader.loadModelOnce( "../myGunModel" )
self.gunModel.reparentTo( camera )
self.gunModel.setPos( 0, 0, -3 )

# Obtain the gunBarrel and its position
self.gunBarrel = self.gunModel.find( "**/barrelLocator" )
pos = self.gunBarrel.getPos()

Now, there are a couple of situations where this will not work outright. If the gun is loaded as an Actor, you must realize that the hierarchy of the model will be lost because the Actor classes optimizes the geometry by flattening the hierarchy, ie reducing the number of nodes in the scene graph. In this case, you would want to use a Maya/Max joint and expose it as Josh suggested.

At Schell Games, we typically use locators in the model file unless the model contains animations, then we will use a joint and expose it. However, my point was mainly to show how you can use the find utility method on NodePath to search the underlying hierarchy of the tree for a specific node.

On a side note, David, I have a question for you. If I load the gun model as an actor, but I have tagged the barrel node as “Model” with the Maya flag; will the barrel node hierarchy be preserved or will it be flattened regardless of the tag? I haven’t bothered testing this out in the past since we have always used joints in this situation.

On a side note, David, I have a question for you. If I load the gun model as an actor, but I have tagged the barrel node as "Model" with the Maya flag; will the barrel node hierarchy be preserved or will it be flattened regardless of the tag? I haven't bothered testing this out in the past since we have always used joints in this situation.

Unfortunately, the Model flag is ignored in this case. It’s arguably a bug in the design of the actor loader, and eventually I do plan to correct this, but that’s the way it is at the moment.

David