diff options
Diffstat (limited to '')
| -rw-r--r-- | scene/3d/car_body.cpp | 741 |
1 files changed, 741 insertions, 0 deletions
diff --git a/scene/3d/car_body.cpp b/scene/3d/car_body.cpp new file mode 100644 index 000000000..a21598b07 --- /dev/null +++ b/scene/3d/car_body.cpp @@ -0,0 +1,741 @@ +/*************************************************************************/ +/* car_body.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "car_body.h" + +#define DEG2RADMUL (Math_PI/180.0) +#define RAD2DEGMUL (180.0/Math_PI) + +void CarWheel::_notification(int p_what) { + + + if (p_what==NOTIFICATION_ENTER_SCENE) { + + if (!get_parent()) + return; + CarBody *cb = get_parent()->cast_to<CarBody>(); + if (!cb) + return; + body=cb; + local_xform=get_transform(); + cb->wheels.push_back(this); + } + if (p_what==NOTIFICATION_EXIT_SCENE) { + + if (!get_parent()) + return; + CarBody *cb = get_parent()->cast_to<CarBody>(); + if (!cb) + return; + cb->wheels.erase(this); + body=NULL; + } +} + +void CarWheel::set_side_friction(real_t p_friction) { + + side_friction=p_friction; +} +void CarWheel::set_forward_friction(real_t p_friction) { + + forward_friction=p_friction; +} +void CarWheel::set_travel(real_t p_travel) { + + travel=p_travel; + update_gizmo(); + +} +void CarWheel::set_radius(real_t p_radius) { + + radius=p_radius; + update_gizmo(); + +} +void CarWheel::set_resting_frac(real_t p_frac) { + + resting_frac=p_frac; +} +void CarWheel::set_damping_frac(real_t p_frac) { + + damping_frac=p_frac; +} +void CarWheel::set_num_rays(real_t p_rays) { + + num_rays=p_rays; +} + +real_t CarWheel::get_side_friction() const{ + + return side_friction; +} +real_t CarWheel::get_forward_friction() const{ + + return forward_friction; +} +real_t CarWheel::get_travel() const{ + + return travel; +} +real_t CarWheel::get_radius() const{ + + return radius; +} +real_t CarWheel::get_resting_frac() const{ + + return resting_frac; +} +real_t CarWheel::get_damping_frac() const{ + + return damping_frac; +} + +int CarWheel::get_num_rays() const{ + + return num_rays; +} + + +void CarWheel::update(real_t dt) { + + + if (dt <= 0.0f) + return; + + float origAngVel = angVel; + + if (locked) + { + angVel = 0; + torque = 0; + } + else + { + + float wheelMass = 0.03f * body->mass; + float inertia = 0.5f * (radius * radius) * wheelMass; + + angVel += torque * dt / inertia; + torque = 0; + + // prevent friction from reversing dir - todo do this better + // by limiting the torque + if (((origAngVel > angVelForGrip) && (angVel < angVelForGrip)) || + ((origAngVel < angVelForGrip) && (angVel > angVelForGrip))) + angVel = angVelForGrip; + + angVel += driveTorque * dt / inertia; + driveTorque = 0; + + float maxAngVel = 200; + print_line("angvel: "+rtos(angVel)); + angVel = CLAMP(angVel, -maxAngVel, maxAngVel); + + axisAngle += Math::rad2deg(dt * angVel); + } +} + +bool CarWheel::add_forces(PhysicsDirectBodyState *s) { + + + Vector3 force; + + PhysicsDirectSpaceState *space = s->get_space_state(); + + Transform world = s->get_transform() * local_xform; + + // OpenGl has differnet row/column order for matrixes than XNA has .. + //Vector3 wheelFwd = world.get_basis().get_axis(Vector3::AXIS_Z); + //Vector3 wheelFwd = RotationMatrix(mSteerAngle, worldAxis) * carBody.GetOrientation().GetCol(0); + Vector3 wheelUp = world.get_basis().get_axis(Vector3::AXIS_Y); + Vector3 wheelFwd = Matrix3(wheelUp,Math::deg2rad(steerAngle)).xform( world.get_basis().get_axis(Vector3::AXIS_Z) ); + Vector3 wheelLeft = -wheelUp.cross(wheelFwd).normalized(); + Vector3 worldPos = world.origin; + Vector3 worldAxis = wheelUp; + + // start of ray + float rayLen = 2.0f * radius + travel; + Vector3 wheelRayEnd = worldPos - radius * worldAxis; + Vector3 wheelRayBegin = wheelRayEnd + rayLen * worldAxis; + //wheelRayEnd = -rayLen * worldAxis; + + //Assert(PhysicsSystem.CurrentPhysicsSystem); + + + ///Assert(collSystem); + /// + const int maxNumRays = 32; + + int numRaysUse = MIN(num_rays, maxNumRays); + + // adjust the start position of the ray - divide the wheel into numRays+2 + // rays, but don't use the first/last. + float deltaFwd = (2.0f * radius) / (numRaysUse + 1); + float deltaFwdStart = deltaFwd; + + float fracs[maxNumRays]; + Vector3 segmentEnds[maxNumRays]; + Vector3 groundPositions[maxNumRays]; + Vector3 groundNormals[maxNumRays]; + + + lastOnFloor = false; + int bestIRay = 0; + int iRay; + + + for (iRay = 0; iRay < numRaysUse; ++iRay) + { + fracs[iRay] = 1e20; + // work out the offset relative to the middle ray + float distFwd = (deltaFwdStart + iRay * deltaFwd) - radius; + float zOffset = radius * (1.0f - (float)Math::cos( Math::deg2rad( 90.0f * (distFwd / radius)))); + + segmentEnds[iRay] = wheelRayEnd + distFwd * wheelFwd + zOffset * wheelUp; + + + PhysicsDirectSpaceState::RayResult rr; + + bool collided = space->intersect_ray(wheelRayBegin,segmentEnds[iRay],rr,body->exclude); + + + if (collided){ + lastOnFloor = true; + groundPositions[iRay]=rr.position; + groundNormals[iRay]=rr.normal; + fracs[iRay] = ((wheelRayBegin-rr.position).length() / (wheelRayBegin-wheelRayEnd).length()); + if (fracs[iRay] < fracs[bestIRay]) + bestIRay = iRay; + } + } + + + if (!lastOnFloor) + return false; + + //Assert(bestIRay < numRays); + + // use the best one + Vector3 groundPos = groundPositions[bestIRay]; + float frac = fracs[bestIRay]; + + // const Vector3 groundNormal = (worldPos - segments[bestIRay].GetEnd()).NormaliseSafe(); + // const Vector3 groundNormal = groundNormals[bestIRay]; + + + Vector3 groundNormal = worldAxis; + + if (numRaysUse > 1) + { + for (iRay = 0; iRay < numRaysUse; ++iRay) + { + if (fracs[iRay] <= 1.0f) + { + groundNormal += (1.0f - fracs[iRay]) * (worldPos - segmentEnds[iRay]); + } + } + + groundNormal.normalize(); + + } + else + { + groundNormal = groundNormals[bestIRay]; + } + + + + float spring = (body->mass/body->wheels.size()) * s->get_total_gravity().length() / (resting_frac * travel); + + float displacement = rayLen * (1.0f - frac); + displacement = CLAMP(displacement, 0, travel); + + + + float displacementForceMag = displacement * spring; + + // reduce force when suspension is par to ground + displacementForceMag *= groundNormals[bestIRay].dot(worldAxis); + + // apply damping + float damping = 2.0f * (float)Math::sqrt(spring * body->mass); + damping /= body->wheels.size(); // assume wheels act together + damping *= damping_frac; // a bit bouncy + + float upSpeed = (displacement - lastDisplacement) / s->get_step(); + + float dampingForceMag = upSpeed * damping; + + float totalForceMag = displacementForceMag + dampingForceMag; + + if (totalForceMag < 0.0f) totalForceMag = 0.0f; + + Vector3 extraForce = totalForceMag * worldAxis; + + + force += extraForce; + // side-slip friction and drive force. Work out wheel- and floor-relative coordinate frame + Vector3 groundUp = groundNormal; + Vector3 groundLeft = groundNormal.cross(wheelFwd).normalized(); + + Vector3 groundFwd = groundLeft.cross(groundUp); + + Vector3 wheelPointVel = s->get_linear_velocity() + + (s->get_angular_velocity()).cross(s->get_transform().basis.xform(local_xform.origin));// * mPos); + + Vector3 rimVel = -angVel * wheelLeft.cross(groundPos - worldPos); + wheelPointVel += rimVel; + + // if sitting on another body then adjust for its velocity. + /*if (worldBody != null) + { + Vector3 worldVel = worldBody.Velocity + + Vector3.Cross(worldBody.AngularVelocity, groundPos - worldBody.Position); + + wheelPointVel -= worldVel; + }*/ + + // sideways forces + float noslipVel = 0.2f; + float slipVel = 0.4f; + float slipFactor = 0.7f; + + float smallVel = 3; + float friction = side_friction; + + float sideVel = wheelPointVel.dot(groundLeft); + + if ((sideVel > slipVel) || (sideVel < -slipVel)) + friction *= slipFactor; + else + if ((sideVel > noslipVel) || (sideVel < -noslipVel)) + friction *= 1.0f - (1.0f - slipFactor) * (Math::absf(sideVel) - noslipVel) / (slipVel - noslipVel); + + if (sideVel < 0.0f) + friction *= -1.0f; + + if (Math::absf(sideVel) < smallVel) + friction *= Math::absf(sideVel) / smallVel; + + float sideForce = -friction * totalForceMag; + + extraForce = sideForce * groundLeft; + force += extraForce; + // fwd/back forces + friction = forward_friction; + float fwdVel = wheelPointVel.dot(groundFwd); + + if ((fwdVel > slipVel) || (fwdVel < -slipVel)) + friction *= slipFactor; + else + if ((fwdVel > noslipVel) || (fwdVel < -noslipVel)) + friction *= 1.0f - (1.0f - slipFactor) * (Math::absf(fwdVel) - noslipVel) / (slipVel - noslipVel); + + if (fwdVel < 0.0f) + friction *= -1.0f; + + if (Math::absf(fwdVel) < smallVel) + friction *= Math::absf(fwdVel) / smallVel; + + float fwdForce = -friction * totalForceMag; + + extraForce = fwdForce * groundFwd; + force += extraForce; + + + //if (!force.IsSensible()) + //{ + // TRACE_FILE_IF(ONCE_1) + // TRACE("Bad force in car wheel\n"); + // return true; + //} + + // fwd force also spins the wheel + Vector3 wheelCentreVel = s->get_linear_velocity() + + (s->get_angular_velocity()).cross(s->get_transform().basis.xform(local_xform.origin)); + + angVelForGrip = wheelCentreVel.dot(groundFwd) / radius; + torque += -fwdForce * radius; + + // add force to car +// carBody.AddWorldForce(force, groundPos); + + s->add_force(force,(groundPos-s->get_transform().origin)); + + // add force to the world + /* + if (worldBody != null && !worldBody.Immovable) + { + // todo get the position in the right place... + // also limit the velocity that this force can produce by looking at the + // mass/inertia of the other object + float maxOtherBodyAcc = 500.0f; + float maxOtherBodyForce = maxOtherBodyAcc * worldBody.Mass; + + if (force.LengthSquared() > (maxOtherBodyForce * maxOtherBodyForce)) + force *= maxOtherBodyForce / force.Length(); + + worldBody.AddWorldForce(-force, groundPos); + }*/ + + Transform wheel_xf = local_xform; + wheel_xf.origin += wheelUp * displacement; + wheel_xf.basis = wheel_xf.basis * Matrix3(Vector3(0,1,0),Math::deg2rad(steerAngle)); + //wheel_xf.basis = wheel_xf.basis * Matrix3(wheel_xf.basis[0],-Math::deg2rad(axisAngle)); + + set_transform(wheel_xf); + lastDisplacement=displacement; + return true; + +} + +void CarWheel::set_type_drive(bool p_enable) { + + type_drive=p_enable; +} + +bool CarWheel::is_type_drive() const { + + return type_drive; +} + +void CarWheel::set_type_steer(bool p_enable) { + + type_steer=p_enable; +} + +bool CarWheel::is_type_steer() const { + + return type_steer; +} + + +void CarWheel::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_side_friction","friction"),&CarWheel::set_side_friction); + ObjectTypeDB::bind_method(_MD("set_forward_friction","friction"),&CarWheel::set_forward_friction); + ObjectTypeDB::bind_method(_MD("set_travel","distance"),&CarWheel::set_travel); + ObjectTypeDB::bind_method(_MD("set_radius","radius"),&CarWheel::set_radius); + ObjectTypeDB::bind_method(_MD("set_resting_frac","frac"),&CarWheel::set_resting_frac); + ObjectTypeDB::bind_method(_MD("set_damping_frac","frac"),&CarWheel::set_damping_frac); + ObjectTypeDB::bind_method(_MD("set_num_rays","amount"),&CarWheel::set_num_rays); + + ObjectTypeDB::bind_method(_MD("get_side_friction"),&CarWheel::get_side_friction); + ObjectTypeDB::bind_method(_MD("get_forward_friction"),&CarWheel::get_forward_friction); + ObjectTypeDB::bind_method(_MD("get_travel"),&CarWheel::get_travel); + ObjectTypeDB::bind_method(_MD("get_radius"),&CarWheel::get_radius); + ObjectTypeDB::bind_method(_MD("get_resting_frac"),&CarWheel::get_resting_frac); + ObjectTypeDB::bind_method(_MD("get_damping_frac"),&CarWheel::get_damping_frac); + ObjectTypeDB::bind_method(_MD("get_num_rays"),&CarWheel::get_num_rays); + + ObjectTypeDB::bind_method(_MD("set_type_drive","enable"),&CarWheel::set_type_drive); + ObjectTypeDB::bind_method(_MD("is_type_drive"),&CarWheel::is_type_drive); + + ObjectTypeDB::bind_method(_MD("set_type_steer","enable"),&CarWheel::set_type_steer); + ObjectTypeDB::bind_method(_MD("is_type_steer"),&CarWheel::is_type_steer); + + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"type/drive"),_SCS("set_type_drive"),_SCS("is_type_drive")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"type/steer"),_SCS("set_type_steer"),_SCS("is_type_steer")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/side_friction",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_side_friction"),_SCS("get_side_friction")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/forward_friction",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_forward_friction"),_SCS("get_forward_friction")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/travel",PROPERTY_HINT_RANGE,"0.01,1024,0.01"),_SCS("set_travel"),_SCS("get_travel")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/radius",PROPERTY_HINT_RANGE,"0.01,1024,0.01"),_SCS("set_radius"),_SCS("get_radius")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/resting_frac",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_resting_frac"),_SCS("get_resting_frac")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/damping_frac",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_damping_frac"),_SCS("get_damping_frac")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/num_rays",PROPERTY_HINT_RANGE,"1,32,1"),_SCS("set_num_rays"),_SCS("get_num_rays")); + +} + +CarWheel::CarWheel() { + + side_friction=4.7; + forward_friction=5.0; + travel=0.2; + radius=0.4; + resting_frac=0.45; + damping_frac=0.3; + num_rays=1; + + angVel = 0.0f; + steerAngle = 0.0f; + torque = 0.0f; + driveTorque = 0.0f; + axisAngle = 0.0f; + upSpeed = 0.0f; + locked = false; + lastDisplacement = 0.0f; + lastOnFloor = false; + angVelForGrip = 0.0f; + angVelForGrip=0; + + type_drive=false; + type_steer=false; + +} + +/// + + +void CarBody::set_max_steer_angle(real_t p_angle) { + + max_steer_angle=p_angle; +} +void CarBody::set_steer_rate(real_t p_rate) { + + steer_rate=p_rate; +} +void CarBody::set_drive_torque(real_t p_torque) { + + drive_torque=p_torque; +} + +real_t CarBody::get_max_steer_angle() const{ + + return max_steer_angle; +} +real_t CarBody::get_steer_rate() const{ + + return steer_rate; +} +real_t CarBody::get_drive_torque() const{ + + return drive_torque; +} + + +void CarBody::set_target_steering(float p_steering) { + + target_steering=p_steering; +} + +void CarBody::set_target_accelerate(float p_accelerate) { + target_accelerate=p_accelerate; +} + +void CarBody::set_hand_brake(float p_amont) { + + hand_brake=p_amont; +} + +real_t CarBody::get_target_steering() const { + + return target_steering; +} +real_t CarBody::get_target_accelerate() const { + + return target_accelerate; +} +real_t CarBody::get_hand_brake() const { + + return hand_brake; +} + + +void CarBody::_direct_state_changed(Object *p_state) { + + PhysicsDirectBodyState *state=p_state->cast_to<PhysicsDirectBodyState>(); + + float dt = state->get_step(); + AABB aabb; + int drive_total=0; + for(int i=0;i<wheels.size();i++) { + CarWheel *w=wheels[i]; + if (i==0) { + aabb.pos=w->local_xform.origin; + } else { + aabb.expand_to(w->local_xform.origin); + } + if (w->type_drive) + drive_total++; + + } + // control inputs + float deltaAccelerate = dt * 4.0f; + + float dAccelerate = target_accelerate - accelerate; + dAccelerate = CLAMP(dAccelerate, -deltaAccelerate, deltaAccelerate); + accelerate += dAccelerate; + + float deltaSteering = dt * steer_rate; + float dSteering = target_steering - steering; + dSteering = CLAMP(dSteering, -deltaSteering, deltaSteering); + steering += dSteering; + + // apply these inputs + float maxTorque = drive_torque; + + float torque_div = drive_total/2; + if (torque_div>0) + maxTorque/=torque_div; + + + float alpha = ABS(max_steer_angle * steering); + float angleSgn = steering > 0.0f ? 1.0f : -1.0f; + + int wheels_on_floor=0; + + for(int i=0;i<wheels.size();i++) { + + CarWheel *w=wheels[i]; + if (w->type_drive) + w->driveTorque+=maxTorque * accelerate; + w->locked = !w->type_steer && (hand_brake > 0.5f); + + if (w->type_steer) { + //steering + + bool inner = (steering > 0 && w->local_xform.origin.x > 0) || (steering < 0 && w->local_xform.origin.x < 0); + + if (inner || alpha==0.0) { + + w->steerAngle = (angleSgn * alpha); + } else { + float dx = aabb.size.z; + float dy = aabb.size.x; + + float beta = Math::atan2(dy, dx + (dy / (float)Math::tan(Math::deg2rad(alpha)))); + beta = Math::rad2deg(beta); + w->steerAngle = (angleSgn * beta); + + } + } + + if (w->add_forces(state)) + wheels_on_floor++; + w->update(dt); + + + } + + print_line("onfloor: "+itos(wheels_on_floor)); + + + set_ignore_transform_notification(true); + set_global_transform(state->get_transform()); + linear_velocity=state->get_linear_velocity(); + angular_velocity=state->get_angular_velocity(); + //active=!state->is_sleeping(); + //if (get_script_instance()) + // get_script_instance()->call("_integrate_forces",state); + set_ignore_transform_notification(false); + + +} + +void CarBody::set_mass(real_t p_mass) { + + mass=p_mass; + PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_MASS,mass); +} + +real_t CarBody::get_mass() const{ + + return mass; +} + + +void CarBody::set_friction(real_t p_friction) { + + friction=p_friction; + PhysicsServer::get_singleton()->body_set_param(get_rid(),PhysicsServer::BODY_PARAM_FRICTION,friction); +} + +real_t CarBody::get_friction() const{ + + return friction; +} + + +void CarBody::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_max_steer_angle","value"),&CarBody::set_max_steer_angle); + ObjectTypeDB::bind_method(_MD("set_steer_rate","rate"),&CarBody::set_steer_rate); + ObjectTypeDB::bind_method(_MD("set_drive_torque","value"),&CarBody::set_drive_torque); + + ObjectTypeDB::bind_method(_MD("get_max_steer_angle"),&CarBody::get_max_steer_angle); + ObjectTypeDB::bind_method(_MD("get_steer_rate"),&CarBody::get_steer_rate); + ObjectTypeDB::bind_method(_MD("get_drive_torque"),&CarBody::get_drive_torque); + + ObjectTypeDB::bind_method(_MD("set_target_steering","amount"),&CarBody::set_target_steering); + ObjectTypeDB::bind_method(_MD("set_target_accelerate","amount"),&CarBody::set_target_accelerate); + ObjectTypeDB::bind_method(_MD("set_hand_brake","amount"),&CarBody::set_hand_brake); + + ObjectTypeDB::bind_method(_MD("get_target_steering"),&CarBody::get_target_steering); + ObjectTypeDB::bind_method(_MD("get_target_accelerate"),&CarBody::get_target_accelerate); + ObjectTypeDB::bind_method(_MD("get_hand_brake"),&CarBody::get_hand_brake); + + ObjectTypeDB::bind_method(_MD("set_mass","mass"),&CarBody::set_mass); + ObjectTypeDB::bind_method(_MD("get_mass"),&CarBody::get_mass); + + ObjectTypeDB::bind_method(_MD("set_friction","friction"),&CarBody::set_friction); + ObjectTypeDB::bind_method(_MD("get_friction"),&CarBody::get_friction); + + ObjectTypeDB::bind_method(_MD("_direct_state_changed"),&CarBody::_direct_state_changed); + + ADD_PROPERTY( PropertyInfo(Variant::REAL,"body/mass",PROPERTY_HINT_RANGE,"0.01,65536,0.01"),_SCS("set_mass"),_SCS("get_mass")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"body/friction",PROPERTY_HINT_RANGE,"0.01,1,0.01"),_SCS("set_friction"),_SCS("get_friction")); + + ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/max_steer_angle",PROPERTY_HINT_RANGE,"1,90,1"),_SCS("set_max_steer_angle"),_SCS("get_max_steer_angle")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/drive_torque",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_drive_torque"),_SCS("get_drive_torque")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"config/steer_rate",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_steer_rate"),_SCS("get_steer_rate")); + + ADD_PROPERTY( PropertyInfo(Variant::REAL,"drive/target_steering",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_target_steering"),_SCS("get_target_steering")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"drive/target_accelerate",PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_target_accelerate"),_SCS("get_target_accelerate")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"drive/hand_brake",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_hand_brake"),_SCS("get_hand_brake")); + +} + +CarBody::CarBody() : PhysicsBody(PhysicsServer::BODY_MODE_RIGID) { + + forward_drive=true; + backward_drive=true; + max_steer_angle=30; + steer_rate=1; + drive_torque=520; + + target_steering=0; + target_accelerate=0; + hand_brake=0; + + steering=0; + accelerate=0; + + mass=1; + friction=1; + + ccd=false; +// can_sleep=true; + + + + + exclude.insert(get_rid()); + PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(),this,"_direct_state_changed"); + + +} |
