266 lines
7.2 KiB
Haxe
Executable file
266 lines
7.2 KiB
Haxe
Executable file
package armory.trait;
|
|
|
|
import iron.Trait;
|
|
import iron.object.Object;
|
|
import iron.object.CameraObject;
|
|
import iron.object.Transform;
|
|
import iron.system.Time;
|
|
import armory.trait.physics.PhysicsWorld;
|
|
|
|
class VehicleBody extends Trait {
|
|
|
|
#if (!arm_bullet)
|
|
public function new() { super(); }
|
|
#else
|
|
|
|
@prop var wheel0Name: String = "Wheel0";
|
|
@prop var wheel1Name: String = "Wheel1";
|
|
@prop var wheel2Name: String = "Wheel2";
|
|
@prop var wheel3Name: String = "Wheel3";
|
|
|
|
var physics: PhysicsWorld;
|
|
var transform: Transform;
|
|
var camera: CameraObject;
|
|
|
|
var wheels: Array<Object> = [];
|
|
var vehicle: bullet.Bt.RaycastVehicle = null;
|
|
var carChassis: bullet.Bt.RigidBody;
|
|
|
|
var chassis_mass = 600.0;
|
|
var wheelFriction = 1000;
|
|
var suspensionStiffness = 20.0;
|
|
var suspensionDamping = 2.3;
|
|
var suspensionCompression = 4.4;
|
|
var suspensionRestLength = 0.3;
|
|
var rollInfluence = 0.1;
|
|
|
|
var maxEngineForce = 3000.0;
|
|
var maxBreakingForce = 500.0;
|
|
|
|
var engineForce = 0.0;
|
|
var breakingForce = 0.0;
|
|
var vehicleSteering = 0.0;
|
|
|
|
public function new() {
|
|
super();
|
|
iron.Scene.active.notifyOnInit(init);
|
|
}
|
|
|
|
function init() {
|
|
physics = armory.trait.physics.PhysicsWorld.active;
|
|
transform = object.transform;
|
|
camera = iron.Scene.active.camera;
|
|
|
|
for (n in [wheel0Name, wheel1Name, wheel2Name, wheel3Name]) {
|
|
wheels.push(iron.Scene.active.root.getChild(n));
|
|
}
|
|
|
|
var wheelDirectionCS0 = new bullet.Bt.Vector3(0, 0, -1);
|
|
var wheelAxleCS = new bullet.Bt.Vector3(1, 0, 0);
|
|
|
|
var chassisShape = new bullet.Bt.BoxShape(new bullet.Bt.Vector3(
|
|
transform.dim.x / 2,
|
|
transform.dim.y / 2,
|
|
transform.dim.z / 2));
|
|
|
|
var compound = new bullet.Bt.CompoundShape();
|
|
|
|
var localTrans = new bullet.Bt.Transform();
|
|
localTrans.setIdentity();
|
|
localTrans.setOrigin(new bullet.Bt.Vector3(0, 0, 1));
|
|
|
|
compound.addChildShape(localTrans, chassisShape);
|
|
|
|
carChassis = createRigidBody(chassis_mass, compound);
|
|
|
|
// Create vehicle
|
|
var tuning = new bullet.Bt.VehicleTuning();
|
|
var vehicleRayCaster = new bullet.Bt.DefaultVehicleRaycaster(physics.world);
|
|
vehicle = new bullet.Bt.RaycastVehicle(tuning, carChassis, vehicleRayCaster);
|
|
|
|
// Never deactivate the vehicle
|
|
carChassis.setActivationState(bullet.Bt.CollisionObjectActivationState.DISABLE_DEACTIVATION);
|
|
|
|
// Choose coordinate system
|
|
var rightIndex = 0;
|
|
var upIndex = 2;
|
|
var forwardIndex = 1;
|
|
vehicle.setCoordinateSystem(rightIndex, upIndex, forwardIndex);
|
|
|
|
// Add wheels
|
|
for (i in 0...wheels.length) {
|
|
var vehicleWheel = new VehicleWheel(i, wheels[i].transform, object.transform);
|
|
vehicle.addWheel(
|
|
vehicleWheel.getConnectionPoint(),
|
|
wheelDirectionCS0,
|
|
wheelAxleCS,
|
|
suspensionRestLength,
|
|
vehicleWheel.wheelRadius,
|
|
tuning,
|
|
vehicleWheel.isFrontWheel);
|
|
}
|
|
|
|
// Setup wheels
|
|
for (i in 0...vehicle.getNumWheels()){
|
|
var wheel = vehicle.getWheelInfo(i);
|
|
wheel.m_suspensionStiffness = suspensionStiffness;
|
|
wheel.m_wheelsDampingRelaxation = suspensionDamping;
|
|
wheel.m_wheelsDampingCompression = suspensionCompression;
|
|
wheel.m_frictionSlip = wheelFriction;
|
|
wheel.m_rollInfluence = rollInfluence;
|
|
}
|
|
|
|
physics.world.addAction(vehicle);
|
|
|
|
notifyOnUpdate(update);
|
|
}
|
|
|
|
function update() {
|
|
if (vehicle == null) return;
|
|
|
|
var keyboard = iron.system.Input.getKeyboard();
|
|
var forward = keyboard.down(keyUp);
|
|
var backward = keyboard.down(keyDown);
|
|
var left = keyboard.down(keyLeft);
|
|
var right = keyboard.down(keyRight);
|
|
var brake = keyboard.down("space");
|
|
|
|
if (forward) {
|
|
engineForce = maxEngineForce;
|
|
}
|
|
else if (backward) {
|
|
engineForce = -maxEngineForce;
|
|
}
|
|
else if (brake) {
|
|
breakingForce = 100;
|
|
}
|
|
else {
|
|
engineForce = 0;
|
|
breakingForce = 20;
|
|
}
|
|
|
|
if (left) {
|
|
if (vehicleSteering < 0.3) vehicleSteering += Time.step;
|
|
}
|
|
else if (right) {
|
|
if (vehicleSteering > -0.3) vehicleSteering -= Time.step;
|
|
}
|
|
else if (vehicleSteering != 0) {
|
|
var step = Math.abs(vehicleSteering) < Time.step ? Math.abs(vehicleSteering) : Time.step;
|
|
if (vehicleSteering > 0) vehicleSteering -= step;
|
|
else vehicleSteering += step;
|
|
}
|
|
|
|
vehicle.applyEngineForce(engineForce, 2);
|
|
vehicle.setBrake(breakingForce, 2);
|
|
vehicle.applyEngineForce(engineForce, 3);
|
|
vehicle.setBrake(breakingForce, 3);
|
|
vehicle.setSteeringValue(vehicleSteering, 0);
|
|
vehicle.setSteeringValue(vehicleSteering, 1);
|
|
|
|
for (i in 0...vehicle.getNumWheels()) {
|
|
// Synchronize the wheels with the chassis worldtransform
|
|
vehicle.updateWheelTransform(i, true);
|
|
|
|
// Update wheels transforms
|
|
var trans = vehicle.getWheelTransformWS(i);
|
|
var p = trans.getOrigin();
|
|
var q = trans.getRotation();
|
|
wheels[i].transform.localOnly = true;
|
|
wheels[i].transform.loc.set(p.x(), p.y(), p.z());
|
|
wheels[i].transform.rot.set(q.x(), q.y(), q.z(), q.w());
|
|
wheels[i].transform.dirty = true;
|
|
}
|
|
|
|
var trans = carChassis.getWorldTransform();
|
|
var p = trans.getOrigin();
|
|
var q = trans.getRotation();
|
|
transform.loc.set(p.x(), p.y(), p.z());
|
|
transform.rot.set(q.x(), q.y(), q.z(), q.w());
|
|
var up = transform.world.up();
|
|
transform.loc.add(up);
|
|
transform.dirty = true;
|
|
|
|
// TODO: fix parent matrix update
|
|
if (camera.parent != null) camera.parent.transform.buildMatrix();
|
|
camera.buildMatrix();
|
|
}
|
|
|
|
function createRigidBody(mass: Float, shape: bullet.Bt.CompoundShape): bullet.Bt.RigidBody {
|
|
|
|
var localInertia = new bullet.Bt.Vector3(0, 0, 0);
|
|
shape.calculateLocalInertia(mass, localInertia);
|
|
|
|
var centerOfMassOffset = new bullet.Bt.Transform();
|
|
centerOfMassOffset.setIdentity();
|
|
|
|
var startTransform = new bullet.Bt.Transform();
|
|
startTransform.setIdentity();
|
|
startTransform.setOrigin(new bullet.Bt.Vector3(
|
|
transform.loc.x,
|
|
transform.loc.y,
|
|
transform.loc.z));
|
|
startTransform.setRotation(new bullet.Bt.Quaternion(
|
|
transform.rot.x,
|
|
transform.rot.y,
|
|
transform.rot.z,
|
|
transform.rot.w));
|
|
|
|
var myMotionState = new bullet.Bt.DefaultMotionState(startTransform, centerOfMassOffset);
|
|
var cInfo = new bullet.Bt.RigidBodyConstructionInfo(mass, myMotionState, shape, localInertia);
|
|
|
|
var body = new bullet.Bt.RigidBody(cInfo);
|
|
body.setLinearVelocity(new bullet.Bt.Vector3(0, 0, 0));
|
|
body.setAngularVelocity(new bullet.Bt.Vector3(0, 0, 0));
|
|
physics.world.addRigidBody(body);
|
|
|
|
return body;
|
|
}
|
|
|
|
#if arm_azerty
|
|
static inline var keyUp = "z";
|
|
static inline var keyDown = "s";
|
|
static inline var keyLeft = "q";
|
|
static inline var keyRight = "d";
|
|
static inline var keyStrafeUp = "e";
|
|
static inline var keyStrafeDown = "a";
|
|
#else
|
|
static inline var keyUp = "w";
|
|
static inline var keyDown = "s";
|
|
static inline var keyLeft = "a";
|
|
static inline var keyRight = "d";
|
|
static inline var keyStrafeUp = "e";
|
|
static inline var keyStrafeDown = "q";
|
|
#end
|
|
#end
|
|
}
|
|
|
|
class VehicleWheel {
|
|
|
|
#if (!arm_bullet)
|
|
public function new() {}
|
|
#else
|
|
|
|
public var isFrontWheel: Bool;
|
|
public var wheelRadius: Float;
|
|
public var wheelWidth: Float;
|
|
|
|
var locX: Float;
|
|
var locY: Float;
|
|
var locZ: Float;
|
|
|
|
public function new(id: Int, transform: Transform, vehicleTransform: Transform) {
|
|
wheelRadius = transform.dim.z / 2;
|
|
wheelWidth = transform.dim.x > transform.dim.y ? transform.dim.y : transform.dim.x;
|
|
|
|
locX = transform.loc.x;
|
|
locY = transform.loc.y;
|
|
locZ = vehicleTransform.dim.z / 2 + transform.loc.z;
|
|
}
|
|
|
|
public function getConnectionPoint(): bullet.Bt.Vector3 {
|
|
return new bullet.Bt.Vector3(locX, locY, locZ);
|
|
}
|
|
#end
|
|
}
|