Car body's angle not changing box2D C++ - c++

i'm making a side-scrolling car game with box2D.
I'm currently working on the car and it seems that i'm stuck.
The chassis of my car isn't rotating when for example the car is trying to climb a hill. I don't know if its normal or if i should set the angle of the body.
Here's a quick video that shows the problem : https://streamable.com/d802n
This is my code :
b2BodyDef carBox = b2BodyDef();
carBox.position = b2Vec2(bodyCenterPosition.x, bodyCenterPosition.y);
carBox.type = b2_dynamicBody;
car = game->getWorld()->CreateBody(&carBox);
b2PolygonShape carPolygon = b2PolygonShape();
carPolygon.SetAsBox(bodySize.x, bodySize.y);
b2FixtureDef carFix = b2FixtureDef();
carFix.density = 0.0f;
carFix.shape = &carPolygon;
car->CreateFixture(&carFix);
b2PolygonShape headPolygon = b2PolygonShape();
headPolygon.SetAsBox(headSize.x, headSize.y);
for (int i = 0; i < 8; i++) {
headPolygon.m_vertices[i].x -= 8.0f / RATIO;
headPolygon.m_vertices[i].y -= 24.0f / RATIO;
}
b2FixtureDef headFix = b2FixtureDef();
headFix.density = 0.0f;
headFix.shape = &headPolygon;
car->CreateFixture(&headFix);
b2CircleShape circleShape;
circleShape.m_radius = 0.35f;
circleShape.m_p.SetZero();
b2FixtureDef fd;
fd.shape = &circleShape;
fd.density = 1.0f;
fd.friction = 0.9f;
b2BodyDef wheel1Def;
wheel1Def.type = b2_dynamicBody;
wheel1Def.position = b2Vec2(backWheelCenterPosition.x, backWheelCenterPosition.y);
backWheel = game->getWorld()->CreateBody(&wheel1Def);
backWheel->CreateFixture(&fd);
b2BodyDef wheel2Def;
wheel2Def.type = b2_dynamicBody;
wheel2Def.position = b2Vec2(frontWheelCenterPosition.x, frontWheelCenterPosition.y);
frontWheel = game->getWorld()->CreateBody(&wheel2Def);
frontWheel->CreateFixture(&fd);
b2WheelJointDef springDef1;
springDef1.dampingRatio = 50.0f;
springDef1.maxMotorTorque = 1.0f;
springDef1.frequencyHz = 15.0f;
springDef1.motorSpeed = 0.0f;
springDef1.enableMotor = true;
springDef1.Initialize(car, backWheel, backWheel->GetPosition(), sfVecToB2Vec(sf::Vector2f(0.0f, 1.0f)));
backSpring = (b2WheelJoint*) game->getWorld()->CreateJoint(&springDef1);
springDef1.Initialize(car, frontWheel, frontWheel->GetPosition(), sfVecToB2Vec(sf::Vector2f(0.0f, 1.0f)));
frontSpring = (b2WheelJoint*) game->getWorld()->CreateJoint(&springDef1);

It is normal for a body with a fixture having a zero density to behave like an infinite mass. Sounds like that's not what you intended however.
Looking at the code presented, we see that the carFix.density and headFix.density are being set to 0.0f. Set these to a positive non-zero value, like 1.0f, and the dynamic body they're created on should behave more like a physical mass would. That's assuming all of the other fixtures created on that body also have a density that's greater than zero as well.
For a tutorial on fixtures and density, I'd recommend taking a look at iforce2d's Box2D C++ tutorials - Fixtures.
Hope this solves the problem or at least helps.
By the way, I loved the artwork shown in the video!

Related

Box2D - Firing bullet from rotating gun

i have a little trouble as title said: i can't figure out how to shoot the bullet toward the direction the gun is pointing at.
Here's short version code, for my bullet firing:
b2BodyDef bd;
bd.type = b2_dynamicBody;
bd.bullet = true;
bd.position = gun->GetPosition();//bullet start at the middle of the gun
m_bullet = m_world->CreateBody(&bd);
m_bullet->CreateFixture(&fd);
m_bullet->ApplyLinearImpulseToCenter( ??? ,true);
At first i thought first param is the direction you want the body go toward so i put in gun->GetWorldPoint(b2Vec2(0.0f,-5.0f)) (middle of the gun's muzzle). Big miss! After a while i thought i should try put in the vector of current gun's rotation degrees b2Vec2 vect = b2Vec2(cos(angle * PI/180), sin(angle * PI/180)); but then the bullet won't fly at all. Now i am all out of ideas. Please, some light.
Full version of code:
public:
b2Body* m_bullet = NULL;
b2Body* gun;
b2RevoluteJoint* joint1;
b2FixtureDef fd;
TestingStuff()
{
{
//body
b2CircleShape circle1;
circle1.m_radius = 1.6f;
fd.shape = &circle1;
fd.density = 1.0f;
fd.filter.groupIndex = -1;
b2BodyDef bd1;
bd1.type = b2_staticBody;
bd1.position.Set(-5.0f, 9.0f);
b2Body* body1 = m_world->CreateBody(&bd1);
body1->CreateFixture(&fd);
//gun
b2PolygonShape box;
box.SetAsBox(0.5f, 5.0f);
fd.shape = &box;
fd.density = 1.0f;
fd.filter.groupIndex = -1;
b2BodyDef bd2;
bd2.type = b2_dynamicBody;
bd2.position.Set(-5.0f, 8.0f);
gun = m_world->CreateBody(&bd2);
gun->CreateFixture(&fd);
//joint
b2RevoluteJointDef jd1;
jd1.Initialize(gun, body1, bd1.position);
jd1.enableMotor = true;
jd1.maxMotorTorque = 90;
jd1.motorSpeed = 180 * DEGTORAD;//DEGTORAD=0.0174532925199432957f
joint1 = (b2RevoluteJoint*) m_world->CreateJoint(&jd1);
}
}
void Keyboard(int key)
{
switch (key)
{
case GLFW_KEY_COMMA:
if (m_bullet != NULL)
{
m_world->DestroyBody(m_bullet);
m_bullet = NULL;
}
{
//bullet
b2CircleShape shape;
shape.m_radius = 0.25f;
fd.shape = &shape;
fd.density = 1;
fd.restitution = 0.05f;
fd.filter.groupIndex = -1;
b2BodyDef bd;
bd.type = b2_dynamicBody;
bd.bullet = true;
bd.position = gun->GetPosition();
m_bullet = m_world->CreateBody(&bd);
m_bullet->CreateFixture(&fd);
m_bullet->ApplyLinearImpulseToCenter( ??? ,true);
}
break;
}
}
After a good sleep i found the solution after few more trial and error.
//bullet
float degAngle = joint1->GetJointAngle() * RADTODEG + 180;
b2Vec2 vect = b2Vec2(sin(degAngle* (b2_pi / 180)) * 10, cos(degAngle* (b2_pi / 180)) * 10);
m_bullet->ApplyLinearImpulseToCenter(vect ,true);
The * 10 is to increase the impulse, make the bullet fly faster and farther, for the sake of testing i just make it 10. Notice that this code is just for testing, if you want to make it more realistic, increase the impulse as well as make the bullet go toward the muzzle instead of go toward the vector it had been fired at.

OpenGL First person camera

I'm trying to do a first cam person using OPENGL. But here's my problem.
Let me introduce you my code.
First of all, I have this function that allows me to get the mouse X and Y position:
case WM_MOUSEMOVE:
CameraManager.oldMouseX = CameraManager.mouseX;
CameraManager.oldMouseY = CameraManager.mouseY;
CameraManager.mouseX = GET_X_LPARAM(lParam);
CameraManager.mouseY = GET_Y_LPARAM(lParam);
mousePoint.x = CameraManager.mouseX - CameraManager.oldMouseX;
mousePoint.y = CameraManager.mouseY - CameraManager.oldMouseY;
mousePoint.z = 0.f;
CameraManager.lookAt(mousePoint);
App.onRender();
break;
Here I get the difference between the old mouse position and the new one (just because I want to know when I have to increase/decrease the angle). Then, I call the lookAt function on my CameraManager.
Here I do the following:
if (point.x > 0.f) {
camAngle.x -= 0.3f;
}
else if (point.x < 0.f) {
camAngle.x += 0.3f ;
}
float radiansX = MathUtils::CalculateRadians(camAngle.x);
//eye.x = sinf(radiansX);
//center.x += sinf(radiansX);
//center.z += (-cosf(radiansX));
Update();
And then my update does:
glLoadIdentity();
gluLookAt(eye.x, eye.y, eye.z,
center.x, center.y, center.z,
up.x, up.y, up.z);
I've read a lot of stuff on how to refresh the eye and center, but I couldn't get anything to work.
Any advices?

Solar System Simulator Physics Integration Issues (Unreal Engine 4, C++)

So I'm making this solar system simulator in Unreal Engine 4 using C++ for a College project, however, I'm new to C++ and UE4 AND I suck at maths so I was in need of a bit of assistance, I wanted to use the Euler integrator for now just to get some basic physics in and have the Moon orbit around the Earth and then move on to probably use the Velocity Verlet method and build the whole Solar System that way. However, as of right now, even the Euler integration doesn't work. Here's the code in Moon.cpp
//Declare the masses
float MMass = 109.456;
float EMass = 1845.833;
//New velocities
float NewMVelX = 0.0;
float NewMVelY = 0.0;
float NewMVelZ = 0.0;
//Distance
float DistanceX = 0.0;
float DistanceY = 0.0;
float DistanceZ = 0.0;
//Earth's velocity
float EVelocityX = 0.0;
float EVelocityY = 0.0;
float EVelocityZ = 0.0;
//Moon's base velocity
float MVelocityX = 0.1;
float MVelocityY = 0.0;
float MVelocityZ = 0.0;
//Moon's acceleration
float MForceX = 0.0;
float MForceY = 0.0;
float MForceZ = 0.0;
//New position
float MPositionX = 0.0;
float MPositionY = 0.0;
float MPositionZ = 0.0;
// Called every frame
void AMoon::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
//Get Earth Location
FVector EPosition = FVector(0.0, 0.0, 0.0);
//Get Moon Location
FVector MPosition = GetActorLocation();
//Get the distance between the 2 bodies
DistanceX = (MPosition.X - EPosition.X) / 100;
DistanceY = (MPosition.Y - EPosition.Y) / 100;
//DistanceZ = MPosition.Z - EPosition.Z / 100;
//Get the acceleration/force for every axis
MForceX = G * MMass * EMass / (DistanceX * DistanceX);
MForceY = G * MMass * EMass / (DistanceY * DistanceY);
//MForceZ = G * MMass * EMass / (DistanceZ * DistanceZ);
//Get the new velocity
NewMVelX = MVelocityX + MForceX;
NewMVelY = MVelocityY + MForceY;
//NewMVelZ = MVelocityZ + MForceZ * DeltaTime;
//Get the new location
MPositionX = (MPosition.X) + NewMVelX;
MPositionY = (MPosition.Y) + NewMVelY;
//MPositionZ = MPosition.Z * (MVelocityZ + NewMVelZ) * 0.5 * DeltaTime;
//Set the new velocity on the old one
MVelocityX = NewMVelX;
MVelocityY = NewMVelY;
//MVelocityZ = NewMVelZ;
//Assign the new location
FVector NewMPosition = FVector(MPositionX, MPositionY, MPositionZ);
//Set the new location
SetActorLocation(NewMPosition);
}
The values might not be right, I was just making tests at this point. I based this code on the different pieces of information I got on Google and multiple websites but at this point I'm quite confused. What is happening is that the Moon just starts going in 1 direction and never stops. I know my issue is with the force/acceleration/actual gravity of the Earth, it should pull the Moon not push it away. But anyway, if anyone has an idea what I'm doing wrong, I'd be very grateful to hear what you have to say! Thanks
The force depends on the euclidean, rotation-invariant distance. Thus use
distance = sqrt(distanceX²+distanceY²+distanceZ²)
force = - G*Emass*Mmass/distance²
forceX = force * X/distance
forceY = force * Y/distance
forceZ = force * Z/distance
The time stepping of the velocity is also wrong, it should be
velocityX += forceX/Mmass * deltaTime
velocityY += forceY/Mmass * deltaTime
velocityZ += forceZ/Mmass * deltaTime
and of course also the position update contains the time step
positionX += velocityX * deltaTime
....

Bullet vehicle wheels fall behind and wrong chassis pitch direction

I have created a bullet vehicle with a attached turret at the top like this:
gEngineForce = 0.f;
gBreakingFrontForce = 0.f;
gBreakingBackForce = 0.f;
maxEngineForce = 20000.f;
minEngineForce = -2000.f;
maxBreakingFrontForce = 4000.f;
maxBreakingBackForce = 600.f;
gVehicleSteering = 0.f;
steeringIncrement = 0.002f;
steeringClamp = 0.6f;
wheelRadius = 0.5f;
wheelWidth = 0.4f;
wheelFriction = 50;
suspensionStiffness = 10.f;
suspensionDamping = 1.3f;
suspensionCompression = 4.4f;
rollInfluence = 0.1f;//1.0f
btScalar suspensionRestLength(0.6);
btVector3 wheelDirectionCS0(0, -1, 0);
btVector3 wheelAxleCS(-1, 0, 0);
btTransform tr;
tr.setIdentity();
chassisShape = new btBoxShape(btVector3(1.f, 0.5f, 2.f));
bulletCollisionShapes.push_back(chassisShape);
compound = new btCompoundShape();
bulletCollisionShapes.push_back(compound);
btTransform chassisTrans;
chassisTrans.setIdentity();
//localTrans effectively shifts the center of mass with respect to the chassis
chassisTrans.setOrigin(btVector3(0, 1.3, 0));
compound->addChildShape(chassisTrans, chassisShape);
tr.setOrigin(btVector3(0, 0.f, 0));
//m_carChassis = CreateRigidBody(2000, tr, compound);
//m_carChassis->setDamping(0.2,0.2);
m_wheelShape = new btCylinderShapeX(btVector3(wheelWidth, wheelRadius, wheelRadius));
m_carChassis = CreateRigidBody(2000, tr, compound);
// create turret
turretShape = new btBoxShape(btVector3(0.4f, 0.2f, 0.8f));
bulletCollisionShapes.push_back(turretShape);
btTransform turretTrans;
turretTrans.setIdentity();
turretTrans.setOrigin(btVector3(0.0f, 0.7f, 0.0f));
turretBody = CreateRigidBody(1, turretTrans, turretShape);
// add some data to build constraint frames
btVector3 axisA(0.f, 1.f, 0.f);
btVector3 axisB(0.f, 0.f, 0.f);
btVector3 pivotA(0.f, 1.f, 0.f);
btVector3 pivotB(0.f, 0.f, 0.f);
hinge = new btHingeConstraint(*m_carChassis, *turretBody, pivotA, pivotB, axisA, axisB);
//hinge->setLimit(-SIMD_HALF_PI * 0.5f, SIMD_HALF_PI * 0.5f);
hinge->enableAngularMotor(true, 0, 1);
// add constraint to world
bt_dynamicsWorld->addConstraint(hinge, true);
{
btTransform something;
something.setIdentity();
something.setOrigin(btVector3(0, 10, 0));
m_carChassis->setWorldTransform(something);
m_vehicleRayCaster = new btDefaultVehicleRaycaster(bt_dynamicsWorld);
m_vehicle = new btRaycastVehicle(m_tuning, m_carChassis, m_vehicleRayCaster);
m_carChassis->setActivationState(DISABLE_DEACTIVATION);
bt_dynamicsWorld->addVehicle(m_vehicle);
float connectionHeight = 1.2f;
//choose coordinate system
m_vehicle->setCoordinateSystem(rightIndex, upIndex, forwardIndex);
bool isFrontWheel = true;
btVector3 connectionPointCS0(1 - (-0.8*wheelWidth), connectionHeight, 3 * 1 - wheelRadius);
m_vehicle->addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, m_tuning, isFrontWheel);
connectionPointCS0 = btVector3(-1 + (-0.8*wheelWidth), connectionHeight, 3 * 1 - wheelRadius);
m_vehicle->addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, m_tuning, isFrontWheel);
isFrontWheel = false;
connectionPointCS0 = btVector3(-1 + (-0.8*wheelWidth), connectionHeight, -3 * 1 + wheelRadius);
m_vehicle->addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, m_tuning, isFrontWheel);
connectionPointCS0 = btVector3(1 - (-0.8*wheelWidth), connectionHeight, -3 * 1 + wheelRadius);
m_vehicle->addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, m_tuning, isFrontWheel);
for (int i = 0; i < m_vehicle->getNumWheels(); i++)
{
btWheelInfo& wheel = m_vehicle->getWheelInfo(i);
wheel.m_suspensionStiffness = suspensionStiffness;
wheel.m_wheelsDampingRelaxation = suspensionDamping;
wheel.m_wheelsDampingCompression = suspensionCompression;
wheel.m_frictionSlip = wheelFriction;
wheel.m_rollInfluence = rollInfluence;
}
}
int wheelIndex = 2;
m_vehicle->applyEngineForce(gEngineForce, wheelIndex);
m_vehicle->setBrake(gBreakingBackForce, wheelIndex);
wheelIndex = 3;
m_vehicle->applyEngineForce(gEngineForce, wheelIndex);
m_vehicle->setBrake(gBreakingBackForce, wheelIndex);
wheelIndex = 0;
m_vehicle->setSteeringValue(gVehicleSteering, wheelIndex);
m_vehicle->setBrake(gBreakingFrontForce, wheelIndex);
wheelIndex = 1;
m_vehicle->setSteeringValue(gVehicleSteering, wheelIndex);
m_vehicle->setBrake(gBreakingFrontForce, wheelIndex);
This is how I render the vehicle:
// render wheels
btScalar mwheel[16];
for (int i = 0; i<m_vehicle->getNumWheels(); i++){
//synchronize the wheels with the (interpolated) chassis worldtransform
m_vehicle->updateWheelTransform(i, true);
//draw wheels
m_vehicle->getWheelInfo(i).m_worldTransform.getOpenGLMatrix(mwheel);
RenderWheel(m_wheelShape, mwheel);
}
// render car chassis
btScalar mchassis[16];
m_vehicle->getChassisWorldTransform().getOpenGLMatrix(mchassis);
RenderBox(chassisShape, mchassis);
// render turret
btScalar mturret[16];
// get chassis and turret transforms
btTransform chassisTransform = m_vehicle->getChassisWorldTransform();
//btTransform turretTransform = compound->getChildTransform(1);
btTransform turretTransform = turretBody->getWorldTransform();
// multiply transforms to get updated turret transform
//turretTransform *= chassisTransform;
turretTransform.getOpenGLMatrix(mturret);
RenderBox(turretShape, mturret);
Using the arrow keys I apply break or acceleration forces like this:
bullet.gEngineForce = bullet.maxEngineForce;
bullet.gBreakingFrontForce = 0.f;
bullet.gBreakingBackForce = 0.f;
etc.
The camera is attached to the turret on top of the car, therefore attached to the car itself.
The issue is that when the car starts moving and as it gain speed, the wheels seem to fall behind and the chassis going forward. I would like make the wheels and the chassis more tight, but playing around with the car suspension settings did not help.
Here is a video demonstrating this behaviour: click
I have also noticed another strange behaviour related to the way the car pitches when moving, breaking and turning.
Increasing the gravity accentuates this behaviour. when I accelerate, the chassis pitches forward and when I brake it goes backwards. This is obviously wrong as it should be the other way around. Same happens when turning left, the car pitches left instead of right, and the other way around.
Here is another video demonstrating this behaviour: click
i had this kind of problem. it turned out that wheels were rendered using transformation not from the same frame as chassis. i.e. from frame n-1 while chassis used frame n.
things werent apparent bcause wheel meshes were child nodes of chassis node, as it was how it was implemented by me in rendering engine, while in bullet physics, wheel coordinates are global, the same way chassis is.
but that wasnt all, when converting wheel coords from global to local vehicle space, there was accuracy loss that, still caused problems. it was fixed by making wheel meshes as global nodes.

Joint on the edge of the circle

The green square is the box2d ground.
The bigger circle is connected to the ground by revolute joint, and can be rotated.
All the circles are b2_dynamicBody
I want to joint the smaller circles on the edge or border of the bigger circle as shown below.
Please tell me how can i achieve it and what kind of joint i have to use?
Also when i rotate big circle the small circle should stick at its place.
Go through this code....
// create joint between hook big circle
wheelSprite = [[CCSprite alloc] initWithFile:#"heroWheel.png"];
wheelSprite.visible = FALSE;
wheelSprite.scale = 1.0*hero_size_factor;
wheelSprite.rotation = 0.0;
wheelSprite.anchorPoint = CGPointMake(0.5,0.5);
[layer addChild:wheelSprite z:5];
ballBodyDef.userData = wheelSprite;
//create hook between big circle
hook = world->CreateBody(&ballBodyDef);
b2PolygonShape hookShape;
hookShape.SetAsBox(0.2,0.1);
b2FixtureDef hookDef;
hookDef.shape=&hookShape;
hookDef.density=0.5f*hero_size_factor;
hookDef.friction = 0.0f;
hookDef.restitution = 0.0f;
hookDef.filter.groupIndex=heroGroupIndex;
hook->CreateFixture(&hookDef);
//create circle shape fixture
b2CircleShape wheel1,wheel2,wheel3,wheel4;
float wheelRadius = hero_width/4.0f;
//Create fixture with above shape
b2FixtureDef ballShapeDef1,ballShapeDef2,ballShapeDef3,ballShapeDef4;
wheel1.m_p = b2Vec2(wheelRadius, wheelRadius);
wheel1.m_radius = wheelRadius;
ballShapeDef1.shape = &wheel1;
ballShapeDef1.density = 0.0f;
ballShapeDef1.friction = 0.0f;
ballShapeDef1.restitution = 0.0f;
ballShapeDef1.filter.groupIndex=heroGroupIndex;
hook->CreateFixture(&ballShapeDef1);
wheel2.m_radius = wheelRadius;
wheel2.m_p = b2Vec2(-wheelRadius, -wheelRadius);
ballShapeDef2.shape = &wheel2;
ballShapeDef2.density = 0.0f;
ballShapeDef2.friction = 0.0f;
ballShapeDef2.restitution = 0.0f;
ballShapeDef2.filter.groupIndex=heroGroupIndex;
hook->CreateFixture(&ballShapeDef2);
wheel3.m_radius = wheelRadius;
wheel3.m_p = b2Vec2(wheelRadius,-wheelRadius);
ballShapeDef3.shape = &wheel3;
ballShapeDef3.density = 0.0f;
ballShapeDef3.friction = 0.0f;
ballShapeDef3.restitution = 0.0f;
ballShapeDef3.filter.groupIndex=heroGroupIndex;
hook->CreateFixture(&ballShapeDef3);
wheel4.m_radius = wheelRadius;
wheel4.m_p = b2Vec2(-wheelRadius,wheelRadius);
ballShapeDef4.shape = &wheel4;
ballShapeDef4.density = 0.0f;
ballShapeDef4.friction = 0.0f;
ballShapeDef4.restitution = 0.0f;
ballShapeDef4.filter.groupIndex=heroGroupIndex;
hook->CreateFixture(&ballShapeDef4);
//Create Revolute Joints between hook and big circle
b2RevoluteJointDef revoluteJointDef;
revoluteJointDef.bodyA = hook;
revoluteJointDef.bodyB = Leg;
revoluteJointDef.collideConnected = false;
revoluteJointDef.localAnchorA.Set(0.0,0.0);
revoluteJointDef.localAnchorB.Set(0.0,-(hero_height - 0.1));
revoluteJointDef.referenceAngle = 0;
revoluteJointDef.maxMotorTorque = 5.0*hero_size_factor;
Hero_Motor = (b2RevoluteJoint*)world->CreateJoint(&revoluteJointDef);