Page 1 of 1

[SOLVED] Best method for firing projectiles from camera?

Posted: Sun Mar 19, 2017 10:12 pm
by jimjamjack
I've been trying to get firing of projectiles to work in my project for a while now. I'm making a basic first person shooter with OpenGL and Bullet, but so far have only been able to fire projectiles based on the camera's position, and not it's rotation (i.e. my projectiles currently always spawn in front of the camera's XYZ position, regardless of which way I've orientated the camera).

Applying physics to an object defined at a point in XYZ coordinates isn't a problem, the problem is just firing a rigidBody from any camera angle. For example, if I'm facing forward and my gun is facing straight ahead, the projectile is created in front of me and appears just after the gun model ends. But, if I turn to the right, the projectile is still created at the same location.

My current method for trying to get this to work is to draw a projectile with OpenGL in front of the camera, and then rotate it based on the camera's orientation (like the projectile orbits the camera). Then I would get the world-coordinates from the model-to-world matrix, and give those to the rigidBody constructor (for the motionstate).

So since this is giving me some issues, does anyone have any suggestions for alternate/better ways to do this? Does anyone have experience with getting this to work?

Cheers.

Re: Best method for firing projectiles from camera?

Posted: Sun Mar 19, 2017 11:16 pm
by ktfh
Cameras tend to be represented in opengl with a view matrix and projection matrix, create a 3x3 rotation matrix or a quaternion from the view matrix and multiply that by a forward vector like (0,0,1) to get a normal that points where the camera looks. Add this to offset your rigid body's creation location and the rigid body can be shot in this direction by multiplying the normal by a magnitude; myBullet.setLinearVelocity(myForwardVector * magnitude);

Re: Best method for firing projectiles from camera?

Posted: Mon Mar 20, 2017 9:04 pm
by jimjamjack
Thanks for the tip, although I'm not entirely sure how I'd do what you suggested.

How can I get a rotation quaternion from the view matrix, a forward vector, where would I add the offset etc.?

Re: Best method for firing projectiles from camera?

Posted: Thu Mar 23, 2017 11:21 am
by Ziket
Hi!.
You can try get information in this page: https://learnopengl.com/#!Getting-started/Camera
Here is some information about how to get and use the forward and the up vector of the camera :D :D :D

Re: Best method for firing projectiles from camera?

Posted: Thu Mar 23, 2017 9:38 pm
by LastBlow
You may want to first cast a ray and then fire. Here below is a way do it, the variable direction in the second snippet is coming from the raycast or could be the position of your camera.

Code: Select all

glm::vec3 Camera::castRay(glm::ivec2 mousePosition) {

	logStderr(VERBOSE, "mouse position %d, %d...\n", mousePosition.x, mousePosition.y);

	float tanFOV = 1.0f / NEAR_PLANE;
	float aspect = WINDOW_WIDTH / (float)WINDOW_HEIGHT;

	glm::vec3 viewVector = -glm::normalize(m_viewVector);
	viewVector *= FAR_PLANE;

	glm::vec3 upVector = glm::normalize(m_upVector);
	upVector *= FAR_PLANE * tanFOV;

	glm::vec3 rightVector = glm::normalize(m_rightVector);
	rightVector *= FAR_PLANE * tanFOV;
	rightVector *= aspect;

	glm::vec3 center = m_cameraPosition + viewVector;                              

	glm::vec3 horizontalDistance = 1.0f / float(WINDOW_WIDTH) * rightVector;
	glm::vec3 verticalDistance = upVector / float(WINDOW_HEIGHT);

	glm::vec3 raycast = center - 0.5f * rightVector + 0.5f * upVector;

	raycast += (float)mousePosition.x * horizontalDistance;
	raycast -= (float)mousePosition.y * verticalDistance;

	logFileStderr(VERBOSE, "raycast: "); printVec3(raycast);

	return raycast;
}


void Inception::shootGeode(std::string typeGeode, const btVector3& direction) {

	logStderr(VERBOSE, "MESSAGE: Shooting geode(s)...\n");

	std::shared_ptr<Geode> geode;

	glm::vec3 cameraPosition = m_camera->getPosition();
	btVector3 position = glm2bullet(cameraPosition + 3.0f * glm::normalize(m_camera->getTarget() - cameraPosition));

	if (typeGeode == "cube")
		geode = m_objectFactory->createCube("cube", new btBoxShape(btVector3(1.0f, 1.0f, 1.0f)), position, "dice");

	if (typeGeode == "sphere")
		geode = m_objectFactory->createSphere("sphere", new btBoxShape(btVector3(1.0f, 1.0f, 1.0f)), position);

	btVector3 velocity = direction;
	velocity.normalize();
	velocity *= 25.0f;

	geode->getRigidBody()->setLinearVelocity(velocity);
}

Re: Best method for firing projectiles from camera?

Posted: Fri Mar 24, 2017 1:02 am
by jimjamjack
Thanks for the suggestions, I've looked at that tutorial but I'm still unsure unfortunately. :/

And although many games go for the "using raycast then firing" method, but unfortunately I can't since I need my bullet to appear after my gun model and look as if it's actually being fired since I'm drawing its path through the scene.

Re: Best method for firing projectiles from camera?

Posted: Mon Mar 27, 2017 5:00 pm
by ktfh
still stuck on this? I think you almost had it figure out.
something like this should offset and shoot your bullet forward or backward.

Code: Select all

float power = 10.f;
glm::vec3 forward = glm::mat3(glm::inverse(ViewMatrix)) * glm::vec3(0,0,1);
glm::vec3 origin = cameraPos + forward;
glm::vec3 vel = forward * power;
myBulletBody.getWorldTransform().setOrigin(btVector3(origin.x,origin,y,origin.z));
myBulletBody.setLinearVelocity(vel.x,vel.y,vel.z);

Re: Best method for firing projectiles from camera?

Posted: Mon Mar 27, 2017 5:08 pm
by jimjamjack
Thanks guys, works perfectly now. I was just infuriatingly close :p

Using ktfh's method was definitely the best way of doing this (and here I was, trying to do some complex matrix manipulation in OpenGL). Really helped, so cheers.