Browse Source

RaycastVehicle code / comments formatting and AngelScript fix. RegisterRaycastVehicleLibrary function removed and class registration performed as part of Physics library initialization instead.

Lasse Öörni 8 years ago
parent
commit
13cfad66ef

+ 0 - 1
Source/Samples/46_RaycastVehicle/RaycastVehicleDemo.cpp

@@ -56,7 +56,6 @@ URHO3D_DEFINE_APPLICATION_MAIN(RaycastVehicleDemo)
 
 RaycastVehicleDemo::RaycastVehicleDemo(Context* context)
     : Sample(context)
-
 {
     // Register factory and attributes for the Vehicle component so it can be created via CreateComponent, and loaded / saved
     Vehicle::RegisterObject(context);

+ 3 - 6
Source/Samples/46_RaycastVehicle/RaycastVehicleDemo.h

@@ -26,10 +26,8 @@
 
 namespace Urho3D
 {
-
-class Node;
-
-class Scene;
+    class Node;
+    class Scene;
 }
 
 class Vehicle;
@@ -43,7 +41,6 @@ class Vehicle;
 
 class RaycastVehicleDemo : public Sample
 {
-
     URHO3D_OBJECT(RaycastVehicleDemo, Sample);
 
 public:
@@ -73,5 +70,5 @@ private:
     void HandlePostUpdate(StringHash eventType, VariantMap& eventData);
 
     /// The controllable vehicle component.
-    WeakPtr< Vehicle > vehicle_;
+    WeakPtr<Vehicle> vehicle_;
 };

+ 2 - 6
Source/Samples/46_RaycastVehicle/Vehicle.cpp

@@ -19,14 +19,10 @@
 #include <Urho3D/Scene/Scene.h>
 #include <Urho3D/Urho3D.h>
 
+using namespace Urho3D;
+
 const float CHASSIS_WIDTH = 2.6f;
 const float WHEEL_WIDTH = 0.4f;
-#define DELETE_NULL(x) \
-    {                  \
-        if (x)         \
-            delete x;  \
-        x = NULL;      \
-    }
 
 void Vehicle::RegisterObject(Context* context)
 {

+ 67 - 51
Source/Samples/46_RaycastVehicle/Vehicle.h

@@ -1,14 +1,38 @@
+//
+// Copyright (c) 2008-2017 the Urho3D project.
+//
+// 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.
+//
+
 #pragma once
+
 #include <Urho3D/Input/Controls.h>
 #include <Urho3D/Physics/PhysicsUtils.h>
 #include <Urho3D/Scene/LogicComponent.h>
 
 namespace Urho3D
 {
-class Constraint;
-class Node;
-class RigidBody;
+    class Constraint;
+    class Node;
+    class RigidBody;
 }
+
 using namespace Urho3D;
 
 const int CTRL_FORWARD = (1 << 0);
@@ -19,17 +43,22 @@ const int CTRL_BRAKE = (1 << 4);
 const float YAW_SENSITIVITY = 0.1f;
 const float ENGINE_POWER = 10.0f;
 const float MAX_WHEEL_ANGLE = 22.5f;
+
 // Vehicle component, responsible for physical movement according to controls.
 // Encapsulates RaycastVehicle
 class Vehicle : public LogicComponent
 {
     URHO3D_OBJECT(Vehicle, LogicComponent)
-    public :
-        /// Construct.
-        Vehicle(Context* context);
+
+public :
+    /// Construct.
+    Vehicle(Context* context);
+    /// Destruct.
     ~Vehicle();
+
     /// Register object factory and attributes.
     static void RegisterObject(Context* context);
+
     /// Perform post-load after deserialization. Acquire the components from the scene nodes.
     virtual void ApplyAttributes();
 
@@ -38,73 +67,60 @@ class Vehicle : public LogicComponent
 
     /// Handle physics world update. Called by LogicComponent base class.
     virtual void FixedUpdate(float timeStep);
-    /// Updating wheel effects here
+    /// Updating wheel effects here.
     virtual void PostUpdate(float timeStep);
 
     /// Movement controls.
     Controls controls_;
-    /// Get steering value
-    float GetSteering()
-    {
-        return steering_;
-    }
-    /// Set steering value
-    void SetSteering(float steering)
-    {
-        steering_ = steering;
-    }
-    /// Get wheel radius
-    float GetWheelRadius()
-    {
-        return wheelRadius_;
-    }
-    /// Get wheel width
-    float GetWheelWidth()
-    {
-        return wheelWidth_;
-    }
-    /// Used for saving - get IDs of particle nodes (memorizing these)
-    VariantVector GetParticleNodeIDsAttr() const;
-    /// Used for loading - set IDs of particle nodes (creating these)
-    void SetParticleNodeIDsAttr(const VariantVector& value);
+
+    /// Get steering value.
+    float GetSteering() { return steering_; }
+
+    /// Set steering value.
+    void SetSteering(float steering) { steering_ = steering; }
+
+    /// Get wheel radius.
+    float GetWheelRadius() { return wheelRadius_; }
+
+    /// Get wheel width.
+    float GetWheelWidth() { return wheelWidth_; }
 
 private:
-    /// Creates particle emitter
+    /// Creates particle emitter.
     void CreateEmitter(Vector3 place);
+
     /// Current left/right steering amount (-1 to 1.)
     float steering_;
-    /// tmp storage for steering
+    /// Tmp storage for steering
     float vehicleSteering_;
-    /// linear momentum supplied by engine to RigidBody
+    /// Linear momentum supplied by engine to RigidBody
     float engineForce_;
-    /// rotational momentum preventing (dampening) wheels rotation
+    /// Rotational momentum preventing (dampening) wheels rotation
     float brakingForce_;
-    /// maximum linear momentum supplied by engine to RigidBody
+    /// Maximum linear momentum supplied by engine to RigidBody
     float maxEngineForce_;
-    /// stored wheel radius
+    /// Stored wheel radius
     float wheelRadius_;
-    /// suspension rest length (in meters)
+    /// Suspension rest length (in meters)
     float suspensionRestLength_;
-    /// width of wheel (used only in calculation of wheel placement)
+    /// Width of wheel (used only in calculation of wheel placement)
     float wheelWidth_;
-    /// suspension stiffness
+    /// Suspension stiffness
     float suspensionStiffness_;
-    /// suspension damping
+    /// Suspension damping
     float suspensionDamping_;
-    /// suspension compression
+    /// Suspension compression
     float suspensionCompression_;
-    /// wheel friction
+    /// Wheel friction
     float wheelFriction_;
-    /// wheel roll influence (how much car will turn sidewise)
+    /// Wheel roll influence (how much car will turn sidewise)
     float rollInfluence_;
-    // emitter data for saving
-    Vector< Node* > particleEmitterNodeList_;
-    // value to calculate acceleration
+    /// Emitter data for saving.
+    Vector<Node*> particleEmitterNodeList_;
+    /// Value to calculate acceleration.
     Vector3 prevVelocity_;
-    // emitter data for saving
-    VariantVector emitterSaveData_;
-    // storing points for emitters
+    /// Storing points for emitters
     Vector3 connectionPoints_[4];
-    // Do not recreate emitters if they are already created
+    /// Do not recreate emitters if they are already created.
     bool emittersCreated;
 };

+ 19 - 20
Source/Urho3D/AngelScript/PhysicsAPI.cpp

@@ -346,56 +346,55 @@ static void RegisterPhysicsWorld(asIScriptEngine* engine)
 void RegisterRaycastVehicleAPI(asIScriptEngine* engine)
 {
     RegisterComponent<RaycastVehicle>(engine, "RaycastVehicle");
-    // please keep these in the same order as in RaycastVehicle.h
     engine->RegisterObjectMethod("RaycastVehicle", "void AddWheel(Node@+, Vector3, Vector3, float, float, bool)", asMETHOD(RaycastVehicle, AddWheel), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "void ResetSuspension()", asMETHOD(RaycastVehicle, ResetSuspension), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "void UpdateWheelTransform(int, bool)", asMETHOD(RaycastVehicle, UpdateWheelTransform), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RaycastVehicle", "void SetSteeringValue(int, float)", asMETHOD(RaycastVehicle, SetSteeringValue), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelSuspensionStiffness(int, float)", asMETHOD(RaycastVehicle, SetWheelSuspensionStiffness), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelDampingRelaxation(int, float)", asMETHOD(RaycastVehicle, SetWheelDampingRelaxation), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelDampingCompression(int, float)", asMETHOD(RaycastVehicle, SetWheelDampingCompression), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelFrictionSlip(int, float)", asMETHOD(RaycastVehicle, SetWheelFrictionSlip), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelRollInfluence(int, float)", asMETHOD(RaycastVehicle, SetWheelRollInfluence), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RaycastVehicle", "void SetEngineForce(int, float)", asMETHOD(RaycastVehicle, SetEngineForce), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RaycastVehicle", "void SetBrake(int, float)", asMETHOD(RaycastVehicle, SetBrake), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelRadius(int, float)", asMETHOD(RaycastVehicle, SetWheelRadius), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RaycastVehicle", "void ResetWheels()", asMETHOD(RaycastVehicle, ResetWheels), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelRestLength(int, float)", asMETHOD(RaycastVehicle, SetWheelRestLength), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelSkidInfo(int, float)", asMETHOD(RaycastVehicle, SetWheelSkidInfo), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RaycastVehicle", "void SetMaxSuspensionTravel(int, float)", asMETHOD(RaycastVehicle, SetMaxSuspensionTravel), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelDirection(int, Vector3)", asMETHOD(RaycastVehicle, SetWheelDirection), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelAxle(int, Vector3)", asMETHOD(RaycastVehicle, SetWheelAxle), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RaycastVehicle", "void set_maxSideSlipSpeed(float)", asMETHOD(RaycastVehicle, SetMaxSideSlipSpeed), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelSkidInfoCumulative(int, float)", asMETHOD(RaycastVehicle, SetWheelSkidInfoCumulative), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RaycastVehicle", "void Init()", asMETHOD(RaycastVehicle, Init), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "Vector3 GetWheelPosition(int)", asMETHOD(RaycastVehicle, GetWheelPosition), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "Vector3 GetWheelRotation(int)", asMETHOD(RaycastVehicle, GetWheelRotation), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "Vector3 GetWheelConnectionPoint(int)", asMETHOD(RaycastVehicle, GetWheelConnectionPoint), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RaycastVehicle", "int get_numWheels()", asMETHOD(RaycastVehicle, GetNumWheels), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "Node@+ GetWheelNode(int)", asMETHOD(RaycastVehicle, GetWheelNode), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RaycastVehicle", "void SetSteeringValue(int, float)", asMETHOD(RaycastVehicle, SetSteeringValue), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "float GetSteeringValue(int)", asMETHOD(RaycastVehicle, GetSteeringValue), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelSuspensionStiffness(int, float)", asMETHOD(RaycastVehicle, SetWheelSuspensionStiffness), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "float GetWheelSuspensionStiffness(int)", asMETHOD(RaycastVehicle, GetWheelSuspensionStiffness), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelDampingRelaxation(int, float)", asMETHOD(RaycastVehicle, SetWheelDampingRelaxation), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "float GetWheelDampingRelaxation(int)", asMETHOD(RaycastVehicle, GetWheelDampingRelaxation), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelDampingCompression(int, float)", asMETHOD(RaycastVehicle, SetWheelDampingCompression), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "float GetWheelDampingCompression(int)", asMETHOD(RaycastVehicle, GetWheelDampingCompression), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelFrictionSlip(int, float)", asMETHOD(RaycastVehicle, SetWheelFrictionSlip), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "float GetWheelFrictionSlip(int)", asMETHOD(RaycastVehicle, GetWheelFrictionSlip), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelRollInfluence(int, float)", asMETHOD(RaycastVehicle, SetWheelRollInfluence), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "float GetWheelRollInfluence(int)", asMETHOD(RaycastVehicle, GetWheelRollInfluence), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RaycastVehicle", "void SetEngineForce(int, float)", asMETHOD(RaycastVehicle, SetEngineForce), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "float GetEngineForce(int)", asMETHOD(RaycastVehicle, GetEngineForce), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RaycastVehicle", "void SetBrake(int, float)", asMETHOD(RaycastVehicle, SetBrake), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "float GetBrake(int)", asMETHOD(RaycastVehicle, GetBrake), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelRadius(int, float)", asMETHOD(RaycastVehicle, SetWheelRadius), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "float GetWheelRadius(int)", asMETHOD(RaycastVehicle, GetWheelRadius), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RaycastVehicle", "void ResetWheels()", asMETHOD(RaycastVehicle, ResetWheels), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelRestLength(int, float)", asMETHOD(RaycastVehicle, SetWheelRestLength), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "float GetWheelRestLength(int)", asMETHOD(RaycastVehicle, GetWheelRestLength), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelSkidInfo(int, float)", asMETHOD(RaycastVehicle, SetWheelSkidInfo), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "float GetWheelSkidInfo(int)", asMETHOD(RaycastVehicle, GetWheelSkidInfo), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "bool WheelIsGrounded(int)", asMETHOD(RaycastVehicle, WheelIsGrounded), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RaycastVehicle", "void SetMaxSuspensionTravel(int, float)", asMETHOD(RaycastVehicle, SetMaxSuspensionTravel), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "float GetMaxSuspensionTravel(int)", asMETHOD(RaycastVehicle, GetMaxSuspensionTravel), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelDirection(int, Vector3)", asMETHOD(RaycastVehicle, SetWheelDirection), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "Vector3 GetWheelDirection(int)", asMETHOD(RaycastVehicle, GetWheelDirection), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelAxle(int, Vector3)", asMETHOD(RaycastVehicle, SetWheelAxle), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "Vector3 GetWheelAxle(int)", asMETHOD(RaycastVehicle, GetWheelAxle), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "float GetWheelSideSlipSpeed(int)", asMETHOD(RaycastVehicle, GetWheelSideSlipSpeed), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "float get_maxSideSlipSpeed()", asMETHOD(RaycastVehicle, GetMaxSideSlipSpeed), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RaycastVehicle", "void set_maxSideSlipSpeed(float)", asMETHOD(RaycastVehicle, SetMaxSideSlipSpeed), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RaycastVehicle", "void SetWheelSkidInfoCumulative(int, float)", asMETHOD(RaycastVehicle, SetWheelSkidInfoCumulative), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "float GetWheelSkidInfoCumulative(int)", asMETHOD(RaycastVehicle, GetWheelSkidInfoCumulative), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "bool IsFrontWheel(int)", asMETHOD(RaycastVehicle, IsFrontWheel), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "Vector3 GetContactPosition(int)", asMETHOD(RaycastVehicle, GetContactPosition), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "Vector3 GetContactNormal(int)", asMETHOD(RaycastVehicle, GetContactNormal), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "void set_inAirRPM(float)", asMETHOD(RaycastVehicle, SetInAirRPM), asCALL_THISCALL);
     engine->RegisterObjectMethod("RaycastVehicle", "float get_inAirRPM()", asMETHOD(RaycastVehicle, GetInAirRPM), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RaycastVehicle", "void Init()", asMETHOD(RaycastVehicle, Init), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RaycastVehicle", "int get_numWheels()", asMETHOD(RaycastVehicle, GetNumWheels), asCALL_THISCALL);
 }
 
 void RegisterPhysicsAPI(asIScriptEngine* engine)

+ 0 - 1
Source/Urho3D/Engine/Engine.cpp

@@ -149,7 +149,6 @@ Engine::Engine(Context* context) :
     
 #ifdef URHO3D_PHYSICS
     RegisterPhysicsLibrary(context_);
-    RegisterRaycastVehicleLibrary(context_);
 #endif
 
 #ifdef URHO3D_NAVIGATION

+ 54 - 58
Source/Urho3D/LuaScript/pkgs/Physics/RaycastVehicle.pkg

@@ -2,63 +2,59 @@ $#include "Physics/RaycastVehicle.h"
 
 class RaycastVehicle : public LogicComponent
 {
-        RaycastVehicle(Urho3D::Context* context);
-        ~RaycastVehicle();
-        static void RegisterObject(Context* context);
-        virtual void ApplyAttributes();
-        void AddWheel(Node *wheelNode, Vector3 wheelDirection, Vector3 wheelAxle, float restLength, float wheelRadius, bool frontWheel);
-        void ResetSuspension(void);
-        void UpdateWheelTransform(int wheel, bool interpolated);
-        Vector3 GetWheelPosition(int wheel);
-        Quaternion GetWheelRotation(int wheel);
-        Vector3 GetWheelConnectionPoint(int wheel);
-        int GetNumWheels();
-        Node *GetWheelNode(int wheel);
-        void SetSteeringValue(int wheel, float steeringValue);
-        float GetSteeringValue(int wheel) const;
-        void SetWheelSuspensionStiffness(int wheel, float stiffness);
-        float GetWheelSuspensionStiffness(int wheel) const;
-        void SetWheelDampingRelaxation(int wheel, float damping);
-        float GetWheelDampingRelaxation(int wheel) const;
-        void SetWheelDampingCompression(int wheel, float compression);
-        float GetWheelDampingCompression(int wheel) const;
-        void SetWheelFrictionSlip(int wheel, float slip);
-        float GetWheelFrictionSlip(int wheel) const;
-        void SetWheelRollInfluence(int wheel, float rollInfluence);
-        float GetWheelRollInfluence(int wheel) const;
-        void SetEngineForce(int wheel, float force);
-        float GetEngineForce(int wheel) const;
-        void SetBrake(int wheel, float force);
-        float GetBrake(int wheel) const;
-        void SetWheelRadius(int wheel, float wheelRadius);
-        float GetWheelRadius(int wheel) const;
-        void ResetWheels();
-        void SetWheelRestLength(int wheel, float length);
-        float GetWheelRestLength(int wheel) const;
-        void SetWheelSkidInfo(int wheel, float factor);
-        float GetWheelSkidInfo(int wheel) const;
-        bool WheelIsGrounded(int wheel) const;
-        void SetMaxSuspensionTravel(int wheel, float maxSuspensionTravel);
-        float GetMaxSuspensionTravel(int wheel);
-        void SetWheelDirection(int wheel, Vector3 direction);
-        Vector3 GetWheelDirection(int wheel) const;
-        void SetWheelAxle(int wheel, Vector3 axle);
-        Vector3 GetWheelAxle(int wheel) const;
-        float GetWheelSideSlipSpeed(int wheel) const;
-        float GetMaxSideSlipSpeed() const;
-        void SetMaxSideSlipSpeed(float speed);
-        void SetWheelSkidInfoCumulative(int wheel, float skid);
-        float GetWheelSkidInfoCumulative(int wheel) const;
-        bool IsFrontWheel(int wheel) const;
-        Vector3 GetContactPosition(int wheel) const;
-        Vector3 GetContactNormal(int wheel) const;
-        void SetInAirRPM(float rpm);
-        float GetInAirRPM() const;
-        void Init();
-        void FixedUpdate(float timeStep);
-        void FixedPostUpdate(float timeStep);
-        void PostUpdate(float timeStep);
-        VariantVector GetWheelDataForSave() const;
-        void SetLoadedWheelData(const VariantVector& value);
+    RaycastVehicle(Urho3D::Context* context);
+    ~RaycastVehicle();
+    static void RegisterObject(Context* context);
+    virtual void ApplyAttributes();
+    void AddWheel(Node *wheelNode, Vector3 wheelDirection, Vector3 wheelAxle, float restLength, float wheelRadius, bool frontWheel);
+    void ResetSuspension(void);
+    void UpdateWheelTransform(int wheel, bool interpolated);
+    void SetSteeringValue(int wheel, float steeringValue);
+    void SetWheelSuspensionStiffness(int wheel, float stiffness);
+    void SetWheelDampingRelaxation(int wheel, float damping);
+    void SetWheelDampingCompression(int wheel, float compression);
+    void SetWheelFrictionSlip(int wheel, float slip);
+    void SetWheelRollInfluence(int wheel, float rollInfluence);
+    void SetEngineForce(int wheel, float force);
+    void SetBrake(int wheel, float force);
+    void SetWheelRadius(int wheel, float wheelRadius);
+    void ResetWheels();
+    void SetWheelRestLength(int wheel, float length);
+    void SetWheelSkidInfo(int wheel, float factor);
+    bool WheelIsGrounded(int wheel) const;
+    void SetMaxSuspensionTravel(int wheel, float maxSuspensionTravel);
+    void SetWheelDirection(int wheel, Vector3 direction);
+    void SetWheelAxle(int wheel, Vector3 axle);
+    void SetMaxSideSlipSpeed(float speed);
+    void SetWheelSkidInfoCumulative(int wheel, float skid);
+    void SetInAirRPM(float rpm);
+    void Init();
+
+    Vector3 GetWheelPosition(int wheel);
+    Quaternion GetWheelRotation(int wheel);
+    Vector3 GetWheelConnectionPoint(int wheel);
+    int GetNumWheels();
+    Node *GetWheelNode(int wheel);
+    float GetSteeringValue(int wheel) const;
+    float GetWheelSuspensionStiffness(int wheel) const;
+    float GetWheelDampingRelaxation(int wheel) const;
+    float GetWheelDampingCompression(int wheel) const;
+    float GetWheelFrictionSlip(int wheel) const;
+    float GetWheelRollInfluence(int wheel) const;
+    float GetEngineForce(int wheel) const;
+    float GetBrake(int wheel) const;
+    float GetWheelRadius(int wheel) const;
+    float GetWheelRestLength(int wheel) const;
+    float GetWheelSkidInfo(int wheel) const;
+    float GetMaxSuspensionTravel(int wheel);
+    float GetWheelSideSlipSpeed(int wheel) const;
+    float GetMaxSideSlipSpeed() const;
+    float GetWheelSkidInfoCumulative(int wheel) const;
+    Vector3 GetWheelDirection(int wheel) const;
+    bool IsFrontWheel(int wheel) const;
+    Vector3 GetWheelAxle(int wheel) const;
+    Vector3 GetContactPosition(int wheel) const;
+    Vector3 GetContactNormal(int wheel) const;
+    float GetInAirRPM() const;
 };
 

+ 2 - 0
Source/Urho3D/Physics/PhysicsWorld.cpp

@@ -34,6 +34,7 @@
 #include "../Physics/PhysicsEvents.h"
 #include "../Physics/PhysicsUtils.h"
 #include "../Physics/PhysicsWorld.h"
+#include "../Physics/RaycastVehicle.h"
 #include "../Physics/RigidBody.h"
 #include "../Scene/Scene.h"
 #include "../Scene/SceneEvents.h"
@@ -1084,6 +1085,7 @@ void RegisterPhysicsLibrary(Context* context)
     RigidBody::RegisterObject(context);
     Constraint::RegisterObject(context);
     PhysicsWorld::RegisterObject(context);
+    RaycastVehicle::RegisterObject(context);
 }
 
 }

+ 616 - 560
Source/Urho3D/Physics/RaycastVehicle.cpp

@@ -33,603 +33,659 @@
 namespace Urho3D
 {
 
-    class RaycastVehicleData
-    {
-            // raycast vehicle
-            btVehicleRaycaster                  *m_vehicleRayCaster;
-            btRaycastVehicle                    *m_vehicle;
-        public:
-            btRaycastVehicle::btVehicleTuning   m_tuning;
-            RaycastVehicleData()
-            {
-                m_vehicleRayCaster = NULL;
-                m_vehicle = NULL;
-            }
-            ~RaycastVehicleData()
-            {
-                if (m_vehicleRayCaster)
-                {
-                    delete m_vehicleRayCaster;
-                }
-                m_vehicleRayCaster = NULL;
-                if (m_vehicle)
-                {
-                    delete m_vehicle;
-                }
-                m_vehicle = NULL;
-            }
-            btRaycastVehicle *Get()
-            {
-                return m_vehicle;
-            }
-            void Init(Scene *scene, RigidBody *body)
-            {
-                int rightIndex = 0;
-                int upIndex = 1;
-                int forwardIndex = 2;
-                PhysicsWorld *pPhysWorld = scene->GetComponent<PhysicsWorld>();
-                btDynamicsWorld *pbtDynWorld = (btDynamicsWorld*) pPhysWorld->GetWorld();
-
-                m_vehicleRayCaster = new btDefaultVehicleRaycaster(pbtDynWorld);
-                btRigidBody *bthullBody = body->GetBody();
-                m_vehicle = new btRaycastVehicle(m_tuning, bthullBody,
-                                                 m_vehicleRayCaster);
-                pbtDynWorld->addVehicle(m_vehicle);
-
-                m_vehicle->setCoordinateSystem(rightIndex, upIndex, forwardIndex);
-            }
-    };
-
-    RaycastVehicle::RaycastVehicle(Context* context)
-        : LogicComponent(context)
-    {
-        // fixed update() for inputs and post update() to sync wheels for rendering
-        SetUpdateEventMask(USE_FIXEDUPDATE | USE_FIXEDPOSTUPDATE | USE_POSTUPDATE);
-        vehicleData_ = new RaycastVehicleData;
-        wheelNodes_.Clear();
-        activate_ = false;
-        inAirRPM_ = 0.0f;
-        maxSideSlipSpeed_ = 4.0f;
-    }
-    RaycastVehicle::~RaycastVehicle()
-    {
-        delete vehicleData_;
-        wheelNodes_.Clear();
-    }
-    const char* wheelElementNames[] =
-    {
-        "Number of wheels",
-        "   Wheel node id",
-        "   Wheel direction",
-        "   Wheel axle",
-        "   Wheel rest length",
-        "   Wheel radius",
-        "   Wheel is front wheel",
-        "   Steering",
-        "   Connection point vector",
-        "   Original rotation",
-        "   Cumulative skid info",
-        "   Side skip speed",
-        "   Grounded",
-        "   Contact position",
-        "   Contact normal",
-        "   Suspension stiffness",
-        "   Damping relaxation",
-        "   Damping compression",
-        "   Friction slip",
-        "   Roll influence",
-        "   Engine force",
-        "   Brake",
-        0
-    };
-    void RaycastVehicle::RegisterObject(Context* context)
-    {
-        context->RegisterFactory<RaycastVehicle>();
-        URHO3D_MIXED_ACCESSOR_VARIANT_VECTOR_STRUCTURE_ATTRIBUTE("Wheel data", GetWheelDataForSave, SetLoadedWheelData,
-                VariantVector, Variant::emptyVariantVector,
-                wheelElementNames, AM_DEFAULT);
-        URHO3D_ATTRIBUTE("Maximum side slip threshold", float, maxSideSlipSpeed_, 4.0f, AM_DEFAULT);
-        URHO3D_ATTRIBUTE("RPM for wheel motors in air (0=calculate)", float, inAirRPM_, 0.0f, AM_DEFAULT);
-    }
-    VariantVector RaycastVehicle::GetWheelDataForSave() const
+struct RaycastVehicleData
+{
+    RaycastVehicleData()
     {
-        VariantVector ret;
-        ret.Reserve(GetNumWheels() * 22 + 1);
-        ret.Push(GetNumWheels());
-        for (int i = 0; i < GetNumWheels(); i++)
-        {
-            Node *wNode = GetWheelNode(i);
-            int node_id = wNode->GetID();
-            URHO3D_LOGDEBUG("RaycastVehicle: Saving node id = " + String(node_id));
-            ret.Push(node_id);
-            ret.Push(GetWheelDirection(i));
-            ret.Push(GetWheelAxle(i));
-            ret.Push(GetWheelRestLength(i));
-            ret.Push(GetWheelRadius(i));
-            ret.Push(IsFrontWheel(i));
-            ret.Push(GetSteeringValue(i));
-            ret.Push(GetWheelConnectionPoint(i));
-            ret.Push(origRotation_[i]);
-            ret.Push(GetWheelSkidInfoCumulative(i));
-            ret.Push(GetWheelSideSlipSpeed(i));
-            ret.Push(WheelIsGrounded(i));
-            ret.Push(GetContactPosition(i));
-            ret.Push(GetContactNormal(i));       // 14
-            ret.Push(GetWheelSuspensionStiffness(i));
-            ret.Push(GetWheelDampingRelaxation(i));
-            ret.Push(GetWheelDampingCompression(i));
-            ret.Push(GetWheelFrictionSlip(i));
-            ret.Push(GetWheelRollInfluence(i));
-            ret.Push(GetEngineForce(i));
-            ret.Push(GetBrake(i));
-            ret.Push(GetWheelSkidInfo(i));
-        }
-        URHO3D_LOGDEBUG("RaycastVehicle: saved items: " + String(ret.Size()));
-        URHO3D_LOGDEBUG("maxSideSlipSpeed_ value save: " + String(maxSideSlipSpeed_));
-        return ret;
+        vehicleRayCaster_ = 0;
+        vehicle_ = 0;
     }
-    void RaycastVehicle::SetLoadedWheelData(const VariantVector& value)
+
+    ~RaycastVehicleData()
     {
-        if (!vehicleData_)
+        if (vehicleRayCaster_)
         {
-            URHO3D_LOGERROR("RaycastVehicle: vehicleData doesn't exist");
-            return;
+            delete vehicleRayCaster_;
         }
-        if (value.Size() < 2)
+        vehicleRayCaster_ = 0;
+        if (vehicle_)
         {
-            URHO3D_LOGERROR("RaycastVehicle: Incorrect vehicleData");
-            return;
+            delete vehicle_;
         }
-        loadedWheelData_ = value;
+        vehicle_ = 0;
     }
-    void RaycastVehicle::ApplyAttributes()
+
+    btRaycastVehicle *Get()
     {
-        int index = 0;
-        hullBody_ = node_->GetOrCreateComponent<RigidBody>();
-        Scene* scene = GetScene();
-        vehicleData_->Init(scene, hullBody_);
-        VariantVector& value = loadedWheelData_;
-        int numObjects = value[index++].GetInt();
-        int wheelIndex = 0;
-        origRotation_.Clear();
-        skidInfoCumulative_.Clear();
-        wheelSideSlipSpeed_.Clear();
-        for (int i = 0; i < numObjects; i++)
-        {
-            int node_id = value[index++].GetInt();
-            Vector3 direction = value[index++].GetVector3();
-            Vector3 axle = value[index++].GetVector3();
-            float restLength = value[index++].GetFloat();
-            float radius = value[index++].GetFloat();
-            bool isFrontWheel = value[index++].GetBool();
-            float steering = value[index++].GetFloat();
-            Vector3 connectionPoint = value[index++].GetVector3();
-            Quaternion origRotation = value[index++].GetQuaternion();
-            float skidInfoC = value[index++].GetFloat();
-            float sideSlipSpeed = value[index++].GetFloat();
-
-            bool isContact = value[index++].GetBool();
-            Vector3 contactPosition = value[index++].GetVector3();
-            Vector3 contactNormal = value[index++].GetVector3();
-            float suspensionStiffness = value[index++].GetFloat();
-            float dampingRelaxation = value[index++].GetFloat();
-            float dampingCompression = value[index++].GetFloat();
-            float frictionSlip = value[index++].GetFloat();
-            float rollInfluence = value[index++].GetFloat();
-            float engineForce = value[index++].GetFloat();
-            float brake = value[index++].GetFloat();
-            float skidInfo = value[index++].GetFloat();
-            Node *wheelNode = GetScene()->GetNode(node_id);
-            if (!wheelNode)
-            {
-                URHO3D_LOGERROR("RaycastVehicle: Incorrect node id = " + String(node_id) + " index: " + String(index));
-                continue;
-            }
-            btRaycastVehicle *m_vehicle = vehicleData_->Get();
-            int id = GetNumWheels();
-            btVector3 connectionPointCS0(connectionPoint.x_, connectionPoint.y_, connectionPoint.z_);
-            btVector3 wheelDirectionCS0(direction.x_, direction.y_, direction.z_);
-            btVector3 wheelAxleCS(axle.x_, axle.y_, axle.z_);
-            btWheelInfo& wheel = m_vehicle->addWheel(connectionPointCS0,
-                                 wheelDirectionCS0,
-                                 wheelAxleCS,
-                                 restLength,
-                                 radius,
-                                 vehicleData_->m_tuning,
-                                 isFrontWheel);
-            wheelNodes_.Push(wheelNode);
-            origRotation_.Push(origRotation);
-            skidInfoCumulative_.Push(skidInfoC);
-            wheelSideSlipSpeed_.Push(sideSlipSpeed);
-            SetSteeringValue(wheelIndex, steering);
-            wheel.m_raycastInfo.m_isInContact = isContact;
-            wheel.m_raycastInfo.m_contactNormalWS = btVector3(contactNormal.x_, contactNormal.y_, contactNormal.z_);
-            wheel.m_raycastInfo.m_contactPointWS = btVector3(contactPosition.x_, contactPosition.y_, contactPosition.z_);
-            wheel.m_suspensionStiffness = suspensionStiffness;
-            wheel.m_wheelsDampingRelaxation = dampingRelaxation;
-            wheel.m_wheelsDampingCompression = dampingCompression;
-            wheel.m_frictionSlip = frictionSlip;
-            wheel.m_rollInfluence = rollInfluence;
-            wheel.m_engineForce = engineForce;
-            wheel.m_brake = brake;
-            wheel.m_skidInfo = skidInfo;
-            wheelIndex++;
-        }
-        URHO3D_LOGDEBUG("maxSideSlipSpeed_ value: " + String(maxSideSlipSpeed_));
-        URHO3D_LOGDEBUG("loaded items: " + String(index));
-        URHO3D_LOGDEBUG("loaded wheels: " + String(GetNumWheels()));
+        return vehicle_;
     }
-    void RaycastVehicle::Init()
+
+    void Init(Scene *scene, RigidBody *body)
     {
-        hullBody_ = node_->GetOrCreateComponent<RigidBody>();
-        Scene* scene = GetScene();
-        vehicleData_->Init(scene, hullBody_);
+        int rightIndex = 0;
+        int upIndex = 1;
+        int forwardIndex = 2;
+        PhysicsWorld *pPhysWorld = scene->GetComponent<PhysicsWorld>();
+        btDynamicsWorld *pbtDynWorld = (btDynamicsWorld*) pPhysWorld->GetWorld();
+
+        vehicleRayCaster_ = new btDefaultVehicleRaycaster(pbtDynWorld);
+        btRigidBody *bthullBody = body->GetBody();
+        vehicle_ = new btRaycastVehicle(tuning_, bthullBody,
+                                            vehicleRayCaster_);
+        pbtDynWorld->addVehicle(vehicle_);
+
+        vehicle_->setCoordinateSystem(rightIndex, upIndex, forwardIndex);
     }
-    void RaycastVehicle::FixedUpdate(float timeStep)
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        for (int i = 0; i < GetNumWheels(); i++)
+
+    btVehicleRaycaster *vehicleRayCaster_;
+    btRaycastVehicle *vehicle_;
+    btRaycastVehicle::btVehicleTuning   tuning_;
+};
+
+RaycastVehicle::RaycastVehicle(Context* context)
+    : LogicComponent(context)
+{
+    // fixed update() for inputs and post update() to sync wheels for rendering
+    SetUpdateEventMask(USE_FIXEDUPDATE | USE_FIXEDPOSTUPDATE | USE_POSTUPDATE);
+    vehicleData_ = new RaycastVehicleData;
+    wheelNodes_.Clear();
+    activate_ = false;
+    inAirRPM_ = 0.0f;
+    maxSideSlipSpeed_ = 4.0f;
+}
+
+RaycastVehicle::~RaycastVehicle()
+{
+    delete vehicleData_;
+    wheelNodes_.Clear();
+}
+
+const char* wheelElementNames[] =
+{
+    "Number of wheels",
+    "   Wheel node id",
+    "   Wheel direction",
+    "   Wheel axle",
+    "   Wheel rest length",
+    "   Wheel radius",
+    "   Wheel is front wheel",
+    "   Steering",
+    "   Connection point vector",
+    "   Original rotation",
+    "   Cumulative skid info",
+    "   Side skip speed",
+    "   Grounded",
+    "   Contact position",
+    "   Contact normal",
+    "   Suspension stiffness",
+    "   Damping relaxation",
+    "   Damping compression",
+    "   Friction slip",
+    "   Roll influence",
+    "   Engine force",
+    "   Brake",
+    0
+};
+
+void RaycastVehicle::RegisterObject(Context* context)
+{
+    context->RegisterFactory<RaycastVehicle>();
+    URHO3D_MIXED_ACCESSOR_VARIANT_VECTOR_STRUCTURE_ATTRIBUTE("Wheel data", GetWheelDataAttr, SetWheelDataAttr,
+            VariantVector, Variant::emptyVariantVector,
+            wheelElementNames, AM_DEFAULT);
+    URHO3D_ATTRIBUTE("Maximum side slip threshold", float, maxSideSlipSpeed_, 4.0f, AM_DEFAULT);
+    URHO3D_ATTRIBUTE("RPM for wheel motors in air (0=calculate)", float, inAirRPM_, 0.0f, AM_DEFAULT);
+}
+
+void RaycastVehicle::ApplyAttributes()
+{
+    int index = 0;
+    hullBody_ = node_->GetOrCreateComponent<RigidBody>();
+    Scene* scene = GetScene();
+    vehicleData_->Init(scene, hullBody_);
+    VariantVector& value = loadedWheelData_;
+    int numObjects = value[index++].GetInt();
+    int wheelIndex = 0;
+    origRotation_.Clear();
+    skidInfoCumulative_.Clear();
+    wheelSideSlipSpeed_.Clear();
+
+    for (int i = 0; i < numObjects; i++)
+    {
+        int node_id = value[index++].GetInt();
+        Vector3 direction = value[index++].GetVector3();
+        Vector3 axle = value[index++].GetVector3();
+        float restLength = value[index++].GetFloat();
+        float radius = value[index++].GetFloat();
+        bool isFrontWheel = value[index++].GetBool();
+        float steering = value[index++].GetFloat();
+        Vector3 connectionPoint = value[index++].GetVector3();
+        Quaternion origRotation = value[index++].GetQuaternion();
+        float skidInfoC = value[index++].GetFloat();
+        float sideSlipSpeed = value[index++].GetFloat();
+
+        bool isContact = value[index++].GetBool();
+        Vector3 contactPosition = value[index++].GetVector3();
+        Vector3 contactNormal = value[index++].GetVector3();
+        float suspensionStiffness = value[index++].GetFloat();
+        float dampingRelaxation = value[index++].GetFloat();
+        float dampingCompression = value[index++].GetFloat();
+        float frictionSlip = value[index++].GetFloat();
+        float rollInfluence = value[index++].GetFloat();
+        float engineForce = value[index++].GetFloat();
+        float brake = value[index++].GetFloat();
+        float skidInfo = value[index++].GetFloat();
+        Node *wheelNode = GetScene()->GetNode(node_id);
+        if (!wheelNode)
         {
-            btWheelInfo whInfo = m_vehicle->getWheelInfo(i);
-            if (whInfo.m_engineForce != 0.0f || whInfo.m_steering != 0.0f)
-            {
-                hullBody_->Activate();
-                break;
-            }
+            URHO3D_LOGERROR("RaycastVehicle: Incorrect node id = " + String(node_id) + " index: " + String(index));
+            continue;
         }
-    }
-    void RaycastVehicle::PostUpdate(float timeStep)
+        btRaycastVehicle *vehicle_ = vehicleData_->Get();
+        int id = GetNumWheels();
+        btVector3 connectionPointCS0(connectionPoint.x_, connectionPoint.y_, connectionPoint.z_);
+        btVector3 wheelDirectionCS0(direction.x_, direction.y_, direction.z_);
+        btVector3 wheelAxleCS(axle.x_, axle.y_, axle.z_);
+        btWheelInfo& wheel = vehicle_->addWheel(connectionPointCS0,
+                                wheelDirectionCS0,
+                                wheelAxleCS,
+                                restLength,
+                                radius,
+                                vehicleData_->tuning_,
+                                isFrontWheel);
+        wheelNodes_.Push(wheelNode);
+        origRotation_.Push(origRotation);
+        skidInfoCumulative_.Push(skidInfoC);
+        wheelSideSlipSpeed_.Push(sideSlipSpeed);
+        SetSteeringValue(wheelIndex, steering);
+        wheel.m_raycastInfo.m_isInContact = isContact;
+        wheel.m_raycastInfo.m_contactNormalWS = btVector3(contactNormal.x_, contactNormal.y_, contactNormal.z_);
+        wheel.m_raycastInfo.m_contactPointWS = btVector3(contactPosition.x_, contactPosition.y_, contactPosition.z_);
+        wheel.m_suspensionStiffness = suspensionStiffness;
+        wheel.m_wheelsDampingRelaxation = dampingRelaxation;
+        wheel.m_wheelsDampingCompression = dampingCompression;
+        wheel.m_frictionSlip = frictionSlip;
+        wheel.m_rollInfluence = rollInfluence;
+        wheel.m_engineForce = engineForce;
+        wheel.m_brake = brake;
+        wheel.m_skidInfo = skidInfo;
+        wheelIndex++;
+    }
+    URHO3D_LOGDEBUG("maxSideSlipSpeed_ value: " + String(maxSideSlipSpeed_));
+    URHO3D_LOGDEBUG("loaded items: " + String(index));
+    URHO3D_LOGDEBUG("loaded wheels: " + String(GetNumWheels()));
+}
+
+void RaycastVehicle::Init()
+{
+    hullBody_ = node_->GetOrCreateComponent<RigidBody>();
+    Scene* scene = GetScene();
+    vehicleData_->Init(scene, hullBody_);
+}
+
+void RaycastVehicle::FixedUpdate(float timeStep)
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    for (int i = 0; i < GetNumWheels(); i++)
     {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        for (int i = 0; i < GetNumWheels(); i++)
+        btWheelInfo whInfo = vehicle_->getWheelInfo(i);
+        if (whInfo.m_engineForce != 0.0f || whInfo.m_steering != 0.0f)
         {
-            m_vehicle->updateWheelTransform(i, true);
-            btTransform transform = m_vehicle->getWheelTransformWS(i);
-            Vector3 origin = ToVector3(transform.getOrigin());
-            Quaternion qRot = ToQuaternion(transform.getRotation());
-            Node *pWheel = wheelNodes_[i];
-            pWheel->SetWorldPosition(origin);
-            pWheel->SetWorldRotation(qRot * origRotation_[i]);
+            hullBody_->Activate();
+            break;
         }
     }
-    void RaycastVehicle::FixedPostUpdate(float timeStep)
+}
+
+void RaycastVehicle::PostUpdate(float timeStep)
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    for (int i = 0; i < GetNumWheels(); i++)
+    {
+        vehicle_->updateWheelTransform(i, true);
+        btTransform transform = vehicle_->getWheelTransformWS(i);
+        Vector3 origin = ToVector3(transform.getOrigin());
+        Quaternion qRot = ToQuaternion(transform.getRotation());
+        Node *pWheel = wheelNodes_[i];
+        pWheel->SetWorldPosition(origin);
+        pWheel->SetWorldRotation(qRot * origRotation_[i]);
+    }
+}
+
+void RaycastVehicle::FixedPostUpdate(float timeStep)
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    Vector3 velocity = hullBody_->GetLinearVelocity();
+    for (int i = 0; i < GetNumWheels(); i++)
     {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        Vector3 velocity = hullBody_->GetLinearVelocity();
-        for (int i = 0; i < GetNumWheels(); i++)
+        btWheelInfo& whInfo = vehicle_->getWheelInfo(i);
+        if (!WheelIsGrounded(i) && GetEngineForce(i) != 0.0f)
         {
-            btWheelInfo& whInfo = m_vehicle->getWheelInfo(i);
-            if (!WheelIsGrounded(i) && GetEngineForce(i) != 0.0f)
+            float delta;
+            if (inAirRPM_ != 0.0f)
             {
-                float delta;
-                if (inAirRPM_ != 0.0f)
-                {
-                    delta = inAirRPM_ * timeStep / 60.0f;
-                }
-                else
-                {
-                    delta = 8.0 * GetEngineForce(i) * timeStep / (hullBody_->GetMass() * GetWheelRadius(i));
-                }
-                if (Abs(whInfo.m_deltaRotation) < Abs(delta))
-                {
-                    whInfo.m_rotation += delta - whInfo.m_deltaRotation;
-                    whInfo.m_deltaRotation = delta;
-                }
-                if (skidInfoCumulative_[i] > 0.05f)
-                {
-                    skidInfoCumulative_[i] -= 0.002;
-                }
+                delta = inAirRPM_ * timeStep / 60.0f;
             }
             else
             {
-                skidInfoCumulative_[i] = GetWheelSkidInfo(i);
+                delta = 8.0f * GetEngineForce(i) * timeStep / (hullBody_->GetMass() * GetWheelRadius(i));
+            }
+            if (Abs(whInfo.m_deltaRotation) < Abs(delta))
+            {
+                whInfo.m_rotation += delta - whInfo.m_deltaRotation;
+                whInfo.m_deltaRotation = delta;
             }
-            wheelSideSlipSpeed_[i] = Abs(ToVector3(whInfo.m_raycastInfo.m_wheelAxleWS).DotProduct(velocity));
-            if (wheelSideSlipSpeed_[i] > maxSideSlipSpeed_)
+            if (skidInfoCumulative_[i] > 0.05f)
             {
-                skidInfoCumulative_[i] = Clamp(skidInfoCumulative_[i], 0.0f, 0.89f);
+                skidInfoCumulative_[i] -= 0.002;
             }
         }
+        else
+        {
+            skidInfoCumulative_[i] = GetWheelSkidInfo(i);
+        }
+        wheelSideSlipSpeed_[i] = Abs(ToVector3(whInfo.m_raycastInfo.m_wheelAxleWS).DotProduct(velocity));
+        if (wheelSideSlipSpeed_[i] > maxSideSlipSpeed_)
+        {
+            skidInfoCumulative_[i] = Clamp(skidInfoCumulative_[i], 0.0f, 0.89f);
+        }
     }
-    void RaycastVehicle::SetMaxSideSlipSpeed(float speed)
-    {
-        maxSideSlipSpeed_ = speed;
-    }
-    float RaycastVehicle::GetMaxSideSlipSpeed() const
-    {
-        return maxSideSlipSpeed_;
-    }
-    void RaycastVehicle::SetWheelSkidInfoCumulative(int wheel, float skid)
-    {
-        skidInfoCumulative_[wheel] = skid;
-    }
-    float RaycastVehicle::GetWheelSkidInfoCumulative(int wheel) const
-    {
-        return skidInfoCumulative_[wheel];
-    }
-    void RaycastVehicle::AddWheel(Node *wheelNode,
-                                  Vector3 wheelDirection, Vector3 wheelAxle,
-                                  float restLength, float wheelRadius,
-                                  bool frontWheel)
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        int id = GetNumWheels();
-        Vector3 connectionPoint = wheelNode->GetWorldPosition() - node_->GetWorldPosition();
-        btVector3 connectionPointCS0(connectionPoint.x_, connectionPoint.y_, connectionPoint.z_);
-        btVector3 wheelDirectionCS0(wheelDirection.x_, wheelDirection.y_, wheelDirection.z_);
-        btVector3 wheelAxleCS(wheelAxle.x_, wheelAxle.y_, wheelAxle.z_);
-        btWheelInfo& wheel = m_vehicle->addWheel(connectionPointCS0,
-                             wheelDirectionCS0,
-                             wheelAxleCS,
-                             restLength,
-                             wheelRadius,
-                             vehicleData_->m_tuning,
-                             frontWheel);
+}
 
-        wheelNodes_.Push(wheelNode);
-        origRotation_.Push(wheelNode->GetWorldRotation());
-        skidInfoCumulative_.Push(1.0f);
-        wheelSideSlipSpeed_.Push(0.0f);
-        wheel.m_raycastInfo.m_isInContact = false;
-    }
-    void RaycastVehicle::ResetSuspension()
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        m_vehicle->resetSuspension();
-    }
-    void RaycastVehicle::UpdateWheelTransform(int wheel, bool interpolated)
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        m_vehicle->updateWheelTransform(wheel, interpolated);
-    }
+void RaycastVehicle::SetMaxSideSlipSpeed(float speed)
+{
+    maxSideSlipSpeed_ = speed;
+}
 
-    Vector3 RaycastVehicle::GetWheelPosition(int wheel)
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btTransform transform = m_vehicle->getWheelTransformWS(wheel);
-        Vector3 origin = ToVector3(transform.getOrigin());
-        return origin;
-    }
-    Quaternion RaycastVehicle::GetWheelRotation(int wheel)
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btTransform transform = m_vehicle->getWheelTransformWS(wheel);
-        Quaternion rotation = ToQuaternion(transform.getRotation());
-        return rotation;
-    }
-    Vector3 RaycastVehicle::GetWheelConnectionPoint(int wheel) const
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo whInfo = m_vehicle->getWheelInfo(wheel);
-        return ToVector3(whInfo.m_chassisConnectionPointCS);
-    }
-    void RaycastVehicle::SetSteeringValue(int wheel, float steeringValue)
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        m_vehicle->setSteeringValue(steeringValue, wheel);
-    }
-    float RaycastVehicle::GetSteeringValue(int wheel) const
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo whInfo = m_vehicle->getWheelInfo(wheel);
-        return whInfo.m_steering;
-    }
-    void RaycastVehicle::SetWheelSuspensionStiffness(int wheel, float stiffness)
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo& whInfo = m_vehicle->getWheelInfo(wheel);
-        whInfo.m_suspensionStiffness = stiffness;
-    }
-    float RaycastVehicle::GetWheelSuspensionStiffness(int wheel) const
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo whInfo = m_vehicle->getWheelInfo(wheel);
-        return whInfo.m_suspensionStiffness;
-    }
-    void RaycastVehicle::SetWheelDampingRelaxation(int wheel, float damping)
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo& whInfo = m_vehicle->getWheelInfo(wheel);
-        whInfo.m_wheelsDampingRelaxation = damping;
-    }
-    float RaycastVehicle::GetWheelDampingRelaxation(int wheel) const
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo whInfo = m_vehicle->getWheelInfo(wheel);
-        return whInfo.m_wheelsDampingRelaxation;
-    }
-    void RaycastVehicle::SetWheelDampingCompression(int wheel, float compression)
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo& whInfo = m_vehicle->getWheelInfo(wheel);
-        whInfo.m_wheelsDampingCompression = compression;
-    }
-    float RaycastVehicle::GetWheelDampingCompression(int wheel) const
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo whInfo = m_vehicle->getWheelInfo(wheel);
-        return whInfo.m_wheelsDampingCompression;
-    }
-    void RaycastVehicle::SetWheelFrictionSlip(int wheel, float slip)
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo& whInfo = m_vehicle->getWheelInfo(wheel);
-        whInfo.m_frictionSlip = slip;
-    }
-    float RaycastVehicle::GetWheelFrictionSlip(int wheel) const
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo whInfo = m_vehicle->getWheelInfo(wheel);
-        return whInfo.m_frictionSlip;
-    }
-    void RaycastVehicle::SetWheelRollInfluence(int wheel, float rollInfluence)
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo& whInfo = m_vehicle->getWheelInfo(wheel);
-        whInfo.m_rollInfluence = rollInfluence;
-    }
-    Vector3 RaycastVehicle::GetContactPosition(int wheel) const
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo& whInfo = m_vehicle->getWheelInfo(wheel);
-        return ToVector3(whInfo.m_raycastInfo.m_contactPointWS);
-    }
-    Vector3 RaycastVehicle::GetContactNormal(int wheel) const
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo& whInfo = m_vehicle->getWheelInfo(wheel);
-        return ToVector3(whInfo.m_raycastInfo.m_contactNormalWS);
-    }
-    float RaycastVehicle::GetWheelSideSlipSpeed(int wheel) const
-    {
-        return wheelSideSlipSpeed_[wheel];
-    }
-    float RaycastVehicle::GetWheelRollInfluence(int wheel) const
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo whInfo = m_vehicle->getWheelInfo(wheel);
-        return whInfo.m_rollInfluence;
-    }
-    void RaycastVehicle::SetWheelRadius(int wheel, float wheelRadius)
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo& whInfo = m_vehicle->getWheelInfo(wheel);
-        whInfo.m_wheelsRadius = wheelRadius;
-    }
-    float RaycastVehicle::GetWheelRadius(int wheel) const
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo& whInfo = m_vehicle->getWheelInfo(wheel);
-        return whInfo.m_wheelsRadius;
-    }
-    void RaycastVehicle::SetEngineForce(int wheel, float force)
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        m_vehicle->applyEngineForce(force, wheel);
-    }
-    float RaycastVehicle::GetEngineForce(int wheel) const
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo whInfo = m_vehicle->getWheelInfo(wheel);
-        return whInfo.m_engineForce;
-    }
-    void RaycastVehicle::SetBrake(int wheel, float force)
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        m_vehicle->setBrake(force, wheel);
-    }
-    float RaycastVehicle::GetBrake(int wheel) const
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo whInfo = m_vehicle->getWheelInfo(wheel);
-        return whInfo.m_brake;
-    }
-    int RaycastVehicle::GetNumWheels() const
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        return m_vehicle->getNumWheels();
-    }
-    Node *RaycastVehicle::GetWheelNode(int wheel) const
-    {
-        return wheelNodes_[wheel];
-    }
-    void RaycastVehicle::SetMaxSuspensionTravel(int wheel, float maxSuspensionTravel)
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo& whInfo = m_vehicle->getWheelInfo(wheel);
-        whInfo.m_maxSuspensionTravelCm = maxSuspensionTravel;
-    }
-    float RaycastVehicle::GetMaxSuspensionTravel(int wheel)
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo whInfo = m_vehicle->getWheelInfo(wheel);
-        return whInfo.m_maxSuspensionTravelCm;
-    }
-    void RaycastVehicle::SetWheelDirection(int wheel, Vector3 direction)
-    {
-        btVector3 dir(direction.x_, direction.y_, direction.z_);
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo& whInfo = m_vehicle->getWheelInfo(wheel);
-        whInfo.m_wheelDirectionCS = dir;
-    }
-    Vector3 RaycastVehicle::GetWheelDirection(int wheel) const
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo& whInfo = m_vehicle->getWheelInfo(wheel);
-        return ToVector3(whInfo.m_wheelDirectionCS);
-    }
-    void RaycastVehicle::SetWheelAxle(int wheel, Vector3 axle)
-    {
-        btVector3 ax(axle.x_, axle.y_, axle.z_);
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo& whInfo = m_vehicle->getWheelInfo(wheel);
-        whInfo.m_wheelAxleCS = ax;
-    }
-    Vector3 RaycastVehicle::GetWheelAxle(int wheel) const
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo& whInfo = m_vehicle->getWheelInfo(wheel);
-        return ToVector3(whInfo.m_wheelAxleCS);
-    }
-    void RaycastVehicle::SetWheelRestLength(int wheel, float length)
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo& whInfo = m_vehicle->getWheelInfo(wheel);
-        whInfo.m_suspensionRestLength1 = length;
-    }
-    float RaycastVehicle::GetWheelRestLength(int wheel) const
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo& whInfo = m_vehicle->getWheelInfo(wheel);
-        return whInfo.m_suspensionRestLength1;
-    }
-    void RaycastVehicle::SetWheelSkidInfo(int wheel, float factor)
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo& whInfo = m_vehicle->getWheelInfo(wheel);
-        whInfo.m_skidInfo = factor;
-    }
-    float RaycastVehicle::GetWheelSkidInfo(int wheel) const
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo& whInfo = m_vehicle->getWheelInfo(wheel);
-        return whInfo.m_skidInfo;
-    }
-    bool RaycastVehicle::IsFrontWheel(int wheel) const
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo& whInfo = m_vehicle->getWheelInfo(wheel);
-        return whInfo.m_bIsFrontWheel;
-    }
-    bool RaycastVehicle::WheelIsGrounded(int wheel) const
-    {
-        btRaycastVehicle *m_vehicle = vehicleData_->Get();
-        btWheelInfo whInfo = m_vehicle->getWheelInfo(wheel);
-        return whInfo.m_raycastInfo.m_isInContact;
-    }
-    void RaycastVehicle::SetInAirRPM(float rpm)
+float RaycastVehicle::GetMaxSideSlipSpeed() const
+{
+    return maxSideSlipSpeed_;
+}
+
+void RaycastVehicle::SetWheelSkidInfoCumulative(int wheel, float skid)
+{
+    skidInfoCumulative_[wheel] = skid;
+}
+
+float RaycastVehicle::GetWheelSkidInfoCumulative(int wheel) const
+{
+    return skidInfoCumulative_[wheel];
+}
+
+void RaycastVehicle::AddWheel(Node *wheelNode,
+                                Vector3 wheelDirection, Vector3 wheelAxle,
+                                float restLength, float wheelRadius,
+                                bool frontWheel)
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    int id = GetNumWheels();
+    Vector3 connectionPoint = wheelNode->GetWorldPosition() - node_->GetWorldPosition();
+    btVector3 connectionPointCS0(connectionPoint.x_, connectionPoint.y_, connectionPoint.z_);
+    btVector3 wheelDirectionCS0(wheelDirection.x_, wheelDirection.y_, wheelDirection.z_);
+    btVector3 wheelAxleCS(wheelAxle.x_, wheelAxle.y_, wheelAxle.z_);
+    btWheelInfo& wheel = vehicle_->addWheel(connectionPointCS0,
+                            wheelDirectionCS0,
+                            wheelAxleCS,
+                            restLength,
+                            wheelRadius,
+                            vehicleData_->tuning_,
+                            frontWheel);
+
+    wheelNodes_.Push(wheelNode);
+    origRotation_.Push(wheelNode->GetWorldRotation());
+    skidInfoCumulative_.Push(1.0f);
+    wheelSideSlipSpeed_.Push(0.0f);
+    wheel.m_raycastInfo.m_isInContact = false;
+}
+
+void RaycastVehicle::ResetSuspension()
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    vehicle_->resetSuspension();
+}
+
+void RaycastVehicle::UpdateWheelTransform(int wheel, bool interpolated)
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    vehicle_->updateWheelTransform(wheel, interpolated);
+}
+
+Vector3 RaycastVehicle::GetWheelPosition(int wheel)
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btTransform transform = vehicle_->getWheelTransformWS(wheel);
+    Vector3 origin = ToVector3(transform.getOrigin());
+    return origin;
+}
+
+Quaternion RaycastVehicle::GetWheelRotation(int wheel)
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btTransform transform = vehicle_->getWheelTransformWS(wheel);
+    Quaternion rotation = ToQuaternion(transform.getRotation());
+    return rotation;
+}
+
+Vector3 RaycastVehicle::GetWheelConnectionPoint(int wheel) const
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo whInfo = vehicle_->getWheelInfo(wheel);
+    return ToVector3(whInfo.m_chassisConnectionPointCS);
+}
+
+void RaycastVehicle::SetSteeringValue(int wheel, float steeringValue)
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    vehicle_->setSteeringValue(steeringValue, wheel);
+}
+
+float RaycastVehicle::GetSteeringValue(int wheel) const
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo whInfo = vehicle_->getWheelInfo(wheel);
+    return whInfo.m_steering;
+}
+
+void RaycastVehicle::SetWheelSuspensionStiffness(int wheel, float stiffness)
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo& whInfo = vehicle_->getWheelInfo(wheel);
+    whInfo.m_suspensionStiffness = stiffness;
+}
+
+float RaycastVehicle::GetWheelSuspensionStiffness(int wheel) const
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo whInfo = vehicle_->getWheelInfo(wheel);
+    return whInfo.m_suspensionStiffness;
+}
+
+void RaycastVehicle::SetWheelDampingRelaxation(int wheel, float damping)
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo& whInfo = vehicle_->getWheelInfo(wheel);
+    whInfo.m_wheelsDampingRelaxation = damping;
+}
+
+float RaycastVehicle::GetWheelDampingRelaxation(int wheel) const
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo whInfo = vehicle_->getWheelInfo(wheel);
+    return whInfo.m_wheelsDampingRelaxation;
+}
+
+void RaycastVehicle::SetWheelDampingCompression(int wheel, float compression)
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo& whInfo = vehicle_->getWheelInfo(wheel);
+    whInfo.m_wheelsDampingCompression = compression;
+}
+
+float RaycastVehicle::GetWheelDampingCompression(int wheel) const
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo whInfo = vehicle_->getWheelInfo(wheel);
+    return whInfo.m_wheelsDampingCompression;
+}
+
+void RaycastVehicle::SetWheelFrictionSlip(int wheel, float slip)
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo& whInfo = vehicle_->getWheelInfo(wheel);
+    whInfo.m_frictionSlip = slip;
+}
+
+float RaycastVehicle::GetWheelFrictionSlip(int wheel) const
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo whInfo = vehicle_->getWheelInfo(wheel);
+    return whInfo.m_frictionSlip;
+}
+
+void RaycastVehicle::SetWheelRollInfluence(int wheel, float rollInfluence)
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo& whInfo = vehicle_->getWheelInfo(wheel);
+    whInfo.m_rollInfluence = rollInfluence;
+}
+
+Vector3 RaycastVehicle::GetContactPosition(int wheel) const
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo& whInfo = vehicle_->getWheelInfo(wheel);
+    return ToVector3(whInfo.m_raycastInfo.m_contactPointWS);
+}
+
+Vector3 RaycastVehicle::GetContactNormal(int wheel) const
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo& whInfo = vehicle_->getWheelInfo(wheel);
+    return ToVector3(whInfo.m_raycastInfo.m_contactNormalWS);
+}
+
+float RaycastVehicle::GetWheelSideSlipSpeed(int wheel) const
+{
+    return wheelSideSlipSpeed_[wheel];
+}
+
+float RaycastVehicle::GetWheelRollInfluence(int wheel) const
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo whInfo = vehicle_->getWheelInfo(wheel);
+    return whInfo.m_rollInfluence;
+}
+
+void RaycastVehicle::SetWheelRadius(int wheel, float wheelRadius)
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo& whInfo = vehicle_->getWheelInfo(wheel);
+    whInfo.m_wheelsRadius = wheelRadius;
+}
+
+float RaycastVehicle::GetWheelRadius(int wheel) const
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo& whInfo = vehicle_->getWheelInfo(wheel);
+    return whInfo.m_wheelsRadius;
+}
+
+void RaycastVehicle::SetEngineForce(int wheel, float force)
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    vehicle_->applyEngineForce(force, wheel);
+}
+
+float RaycastVehicle::GetEngineForce(int wheel) const
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo whInfo = vehicle_->getWheelInfo(wheel);
+    return whInfo.m_engineForce;
+}
+
+void RaycastVehicle::SetBrake(int wheel, float force)
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    vehicle_->setBrake(force, wheel);
+}
+
+float RaycastVehicle::GetBrake(int wheel) const
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo whInfo = vehicle_->getWheelInfo(wheel);
+    return whInfo.m_brake;
+}
+
+int RaycastVehicle::GetNumWheels() const
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    return vehicle_->getNumWheels();
+}
+
+Node *RaycastVehicle::GetWheelNode(int wheel) const
+{
+    return wheelNodes_[wheel];
+}
+
+void RaycastVehicle::SetMaxSuspensionTravel(int wheel, float maxSuspensionTravel)
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo& whInfo = vehicle_->getWheelInfo(wheel);
+    whInfo.m_maxSuspensionTravelCm = maxSuspensionTravel;
+}
+
+float RaycastVehicle::GetMaxSuspensionTravel(int wheel)
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo whInfo = vehicle_->getWheelInfo(wheel);
+    return whInfo.m_maxSuspensionTravelCm;
+}
+
+void RaycastVehicle::SetWheelDirection(int wheel, Vector3 direction)
+{
+    btVector3 dir(direction.x_, direction.y_, direction.z_);
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo& whInfo = vehicle_->getWheelInfo(wheel);
+    whInfo.m_wheelDirectionCS = dir;
+}
+
+Vector3 RaycastVehicle::GetWheelDirection(int wheel) const
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo& whInfo = vehicle_->getWheelInfo(wheel);
+    return ToVector3(whInfo.m_wheelDirectionCS);
+}
+
+void RaycastVehicle::SetWheelAxle(int wheel, Vector3 axle)
+{
+    btVector3 ax(axle.x_, axle.y_, axle.z_);
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo& whInfo = vehicle_->getWheelInfo(wheel);
+    whInfo.m_wheelAxleCS = ax;
+}
+
+Vector3 RaycastVehicle::GetWheelAxle(int wheel) const
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo& whInfo = vehicle_->getWheelInfo(wheel);
+    return ToVector3(whInfo.m_wheelAxleCS);
+}
+
+void RaycastVehicle::SetWheelRestLength(int wheel, float length)
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo& whInfo = vehicle_->getWheelInfo(wheel);
+    whInfo.m_suspensionRestLength1 = length;
+}
+
+float RaycastVehicle::GetWheelRestLength(int wheel) const
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo& whInfo = vehicle_->getWheelInfo(wheel);
+    return whInfo.m_suspensionRestLength1;
+}
+
+void RaycastVehicle::SetWheelSkidInfo(int wheel, float factor)
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo& whInfo = vehicle_->getWheelInfo(wheel);
+    whInfo.m_skidInfo = factor;
+}
+
+float RaycastVehicle::GetWheelSkidInfo(int wheel) const
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo& whInfo = vehicle_->getWheelInfo(wheel);
+    return whInfo.m_skidInfo;
+}
+
+bool RaycastVehicle::IsFrontWheel(int wheel) const
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo& whInfo = vehicle_->getWheelInfo(wheel);
+    return whInfo.m_bIsFrontWheel;
+}
+
+bool RaycastVehicle::WheelIsGrounded(int wheel) const
+{
+    btRaycastVehicle *vehicle_ = vehicleData_->Get();
+    btWheelInfo whInfo = vehicle_->getWheelInfo(wheel);
+    return whInfo.m_raycastInfo.m_isInContact;
+}
+
+void RaycastVehicle::SetInAirRPM(float rpm)
+{
+    inAirRPM_ = rpm;
+}
+
+float RaycastVehicle::GetInAirRPM() const
+{
+    return inAirRPM_;
+}
+
+void RaycastVehicle::ResetWheels()
+{
+    ResetSuspension();
+    for (int i = 0; i < GetNumWheels(); i++)
     {
-        inAirRPM_ = rpm;
+        UpdateWheelTransform(i, true);
+        Vector3 origin = GetWheelPosition(i);
+        Node *wheelNode = GetWheelNode(i);
+        wheelNode->SetWorldPosition(origin);
     }
-    float RaycastVehicle::GetInAirRPM() const
+}
+
+VariantVector RaycastVehicle::GetWheelDataAttr() const
+{
+    VariantVector ret;
+    ret.Reserve(GetNumWheels() * 22 + 1);
+    ret.Push(GetNumWheels());
+    for (int i = 0; i < GetNumWheels(); i++)
+    {
+        Node *wNode = GetWheelNode(i);
+        int node_id = wNode->GetID();
+        URHO3D_LOGDEBUG("RaycastVehicle: Saving node id = " + String(node_id));
+        ret.Push(node_id);
+        ret.Push(GetWheelDirection(i));
+        ret.Push(GetWheelAxle(i));
+        ret.Push(GetWheelRestLength(i));
+        ret.Push(GetWheelRadius(i));
+        ret.Push(IsFrontWheel(i));
+        ret.Push(GetSteeringValue(i));
+        ret.Push(GetWheelConnectionPoint(i));
+        ret.Push(origRotation_[i]);
+        ret.Push(GetWheelSkidInfoCumulative(i));
+        ret.Push(GetWheelSideSlipSpeed(i));
+        ret.Push(WheelIsGrounded(i));
+        ret.Push(GetContactPosition(i));
+        ret.Push(GetContactNormal(i));       // 14
+        ret.Push(GetWheelSuspensionStiffness(i));
+        ret.Push(GetWheelDampingRelaxation(i));
+        ret.Push(GetWheelDampingCompression(i));
+        ret.Push(GetWheelFrictionSlip(i));
+        ret.Push(GetWheelRollInfluence(i));
+        ret.Push(GetEngineForce(i));
+        ret.Push(GetBrake(i));
+        ret.Push(GetWheelSkidInfo(i));
+    }
+    URHO3D_LOGDEBUG("RaycastVehicle: saved items: " + String(ret.Size()));
+    URHO3D_LOGDEBUG("maxSideSlipSpeed_ value save: " + String(maxSideSlipSpeed_));
+    return ret;
+}
+
+void RaycastVehicle::SetWheelDataAttr(const VariantVector& value)
+{
+    if (!vehicleData_)
     {
-        return inAirRPM_;
+        URHO3D_LOGERROR("RaycastVehicle: vehicleData doesn't exist");
+        return;
     }
-    void RaycastVehicle::ResetWheels()
+    if (value.Size() < 2)
     {
-        ResetSuspension();
-        for (int i = 0; i < GetNumWheels(); i++)
-        {
-            UpdateWheelTransform(i, true);
-            Vector3 origin = GetWheelPosition(i);
-            Node *wheelNode = GetWheelNode(i);
-            wheelNode->SetWorldPosition(origin);
-        }
+        URHO3D_LOGERROR("RaycastVehicle: Incorrect vehicleData");
+        return;
     }
 
-    void RegisterRaycastVehicleLibrary(Context* context)
-    {
-        RaycastVehicle::RegisterObject(context);
-    }
+    loadedWheelData_ = value;
+}
 
 } // namespace Urho3D

+ 150 - 148
Source/Urho3D/Physics/RaycastVehicle.h

@@ -27,154 +27,156 @@
 namespace Urho3D
 {
 
-    class RaycastVehicleData;
+struct RaycastVehicleData;
 
-    class URHO3D_API RaycastVehicle : public LogicComponent
-    {
-            URHO3D_OBJECT(RaycastVehicle, LogicComponent)
-        public:
-            /// Construct.
-            RaycastVehicle(Urho3D::Context* context);
-            ~RaycastVehicle();
-            /// Register object factory and attributes.
-            static void RegisterObject(Context* context);
-            /// Perform post-load after deserialization. Acquire the components from the scene nodes.
-            virtual void ApplyAttributes();
-            /// Add a wheel (all parameters are relative to RigidBody/node)
-            void AddWheel(Node *wheelNode, Vector3 wheelDirection, Vector3 wheelAxle, float restLength, float wheelRadius, bool frontWheel);
-            /// Reset all suspension
-            void ResetSuspension(void);
-            /// Update transform for particular wheel
-            void UpdateWheelTransform(int wheel, bool interpolated);
-            /// Get wheel position relative to RigidBody
-            Vector3 GetWheelPosition(int wheel);
-            /// Get wheel rotation relative to RigidBody
-            Quaternion GetWheelRotation(int wheel);
-            /// Get wheel connection point relative to RigidBody
-            Vector3 GetWheelConnectionPoint(int wheel) const;
-            /// Get number of attached wheels
-            int GetNumWheels() const;
-            /// Get Node of the wheel
-            Node *GetWheelNode(int wheel) const;
-            /// Set steering value of particular wheel
-            void SetSteeringValue(int wheel, float steeringValue);
-            /// Get steering value of particular wheel
-            float GetSteeringValue(int wheel) const;
-            /// Set suspension stiffness for particular wheel
-            void SetWheelSuspensionStiffness(int wheel, float stiffness);
-            /// Get suspension stiffness for particular wheel
-            float GetWheelSuspensionStiffness(int wheel) const;
-            /// Set wheel damping relaxation
-            void SetWheelDampingRelaxation(int wheel, float damping);
-            /// Get wheel damping relaxation
-            float GetWheelDampingRelaxation(int wheel) const;
-            /// Set wheel damping compression
-            void SetWheelDampingCompression(int wheel, float compression);
-            /// Get wheel damping compression
-            float GetWheelDampingCompression(int wheel) const;
-            /// Set wheel friction slip
-            void SetWheelFrictionSlip(int wheel, float slip);
-            /// Get wheel friction slip
-            float GetWheelFrictionSlip(int wheel) const;
-            /// Set wheel roll influence
-            void SetWheelRollInfluence(int wheel, float rollInfluence);
-            /// Get wheel roll influence
-            float GetWheelRollInfluence(int wheel) const;
-            /// Set engine force for the wheel
-            void SetEngineForce(int wheel, float force);
-            /// Get engine force for the wheel
-            float GetEngineForce(int wheel) const;
-            /// Set hand brake (wheel rotation blocking force)
-            void SetBrake(int wheel, float force);
-            /// Get hand break value
-            float GetBrake(int wheel) const;
-            /// Set wheel radius
-            void SetWheelRadius(int wheel, float wheelRadius);
-            /// Get wheel radius
-            float GetWheelRadius(int wheel) const;
-            /// Sets node initial positions
-            void ResetWheels();
-            /// Get wheel rest length
-            void SetWheelRestLength(int wheel, float length);
-            /// Get wheel rest length
-            float GetWheelRestLength(int wheel) const;
-            /// Set sliding factor 0 <= x <= 1
-            /// the less the value, more sliding.
-            void SetWheelSkidInfo(int wheel, float factor);
-            /// Sliding factor 0 <= x <= 1
-            float GetWheelSkidInfo(int wheel) const;
-            /// true if wheel touches ground (raycast hits something)
-            bool WheelIsGrounded(int wheel) const;
-            /// Set maximum suspension travel value
-            void SetMaxSuspensionTravel(int wheel, float maxSuspensionTravel);
-            /// Get maximum suspension travel value
-            float GetMaxSuspensionTravel(int wheel);
-            /// Set wheel direction vector
-            void SetWheelDirection(int wheel, Vector3 direction);
-            /// Get wheel direction vector
-            Vector3 GetWheelDirection(int wheel) const;
-            /// Set wheel axle vector
-            void SetWheelAxle(int wheel, Vector3 axle);
-            /// Get wheel axle vector
-            Vector3 GetWheelAxle(int wheel) const;
-            /// Get wheel slide speed
-            float GetWheelSideSlipSpeed(int wheel) const;
-            /// get side speed which is considered sliding
-            float GetMaxSideSlipSpeed() const;
-            /// set side speed which is considered sliding
-            void SetMaxSideSlipSpeed(float speed);
-            /// set cumuative skid info
-            void SetWheelSkidInfoCumulative(int wheel, float skid);
-            /// get cumuative skid info
-            float GetWheelSkidInfoCumulative(int wheel) const;
-            /// true if front wheel, otherwise false
-            bool IsFrontWheel(int wheel) const;
-            /// get wheel contact position
-            Vector3 GetContactPosition(int wheel) const;
-            // get contact normal
-            Vector3 GetContactNormal(int wheel) const;
-            /// Set revolution per minute value for when weel
-            /// doesn't touch ground
-            /// If set to 0 (or not set), calculated from engine force
-            /// (probably not what you want).
-            void SetInAirRPM(float rpm);
-            /// Get revolution per minute value for when weel
-            /// doesn't touch ground
-            float GetInAirRPM() const;
-            /// Init the vehicle component after creation
-            void Init();
-            void FixedUpdate(float timeStep);
-            void FixedPostUpdate(float timeStep);
-            void PostUpdate(float timeStep);
-            VariantVector GetWheelDataForSave() const;
-            void SetLoadedWheelData(const VariantVector& value);
-        private:
-            // If the RigidBody should be activated
-            bool activate_;
-            // Hull RigidBody
-            WeakPtr<RigidBody> hullBody_;
-            // Opaque Bullet data hidden from public
-            RaycastVehicleData *vehicleData_;
-            // Nodes of all wheels
-            Vector<Node*>           wheelNodes_;
-            // All wheels original rotations
-            // These are applied in addition to wheel
-            // rotations by btRaycastVehicle
-            Vector<Quaternion>      origRotation_;
-            // Revolutions per minute value for in-air motor wheels
-            // It is per vehicle. I know, I will fix this later.
-            // FIXME: set this one per wheel
-            float                   inAirRPM_;
-            // Per-wheel extra settings
-            Vector<float> skidInfoCumulative_;
-            // wheel side movement speed
-            Vector<float> wheelSideSlipSpeed_;
-            // side slip speed threshold
-            float maxSideSlipSpeed_;
-            // Loaded data temporarily wait here for ApplyAttributes
-            // to come pick them up
-            VariantVector loadedWheelData_;
-    };
+class URHO3D_API RaycastVehicle : public LogicComponent
+{
+    URHO3D_OBJECT(RaycastVehicle, LogicComponent)
+
+public:
+    /// Construct.
+    RaycastVehicle(Urho3D::Context* context);
+    /// Destruct.
+    ~RaycastVehicle();
+
+    /// Register object factory and attributes.
+    static void RegisterObject(Context* context);
+    
+    /// Perform post-load after deserialization. Acquire the components from the scene nodes.
+    virtual void ApplyAttributes();
+
+    /// Add a wheel. All parameters are relative to RigidBody / node.
+    void AddWheel(Node *wheelNode, Vector3 wheelDirection, Vector3 wheelAxle, float restLength, float wheelRadius, bool frontWheel);
+    /// Reset all suspension.
+    void ResetSuspension(void);
+    /// Update transform for particular wheel.
+    void UpdateWheelTransform(int wheel, bool interpolated);
+    /// Set steering value of particular wheel.
+    void SetSteeringValue(int wheel, float steeringValue);
+    /// Set suspension stiffness for particular wheel.
+    void SetWheelSuspensionStiffness(int wheel, float stiffness);
+    /// Set wheel damping relaxation.
+    void SetWheelDampingRelaxation(int wheel, float damping);
+    /// Set wheel damping compression.
+    void SetWheelDampingCompression(int wheel, float compression);
+    /// Set wheel friction slip.
+    void SetWheelFrictionSlip(int wheel, float slip);
+    /// Set wheel roll influence.
+    void SetWheelRollInfluence(int wheel, float rollInfluence);
+    /// Set engine force for the wheel.
+    void SetEngineForce(int wheel, float force);
+    /// Set hand brake (wheel rotation blocking force.)
+    void SetBrake(int wheel, float force);
+    /// Set wheel radius.
+    void SetWheelRadius(int wheel, float wheelRadius);
+    /// Sets node initial positions.
+    void ResetWheels();
+    /// Set sliding factor 0 <= x <= 1. The less the value, more sliding.
+    void SetWheelSkidInfo(int wheel, float factor);
+    /// True if wheel touches ground (raycast hits something.)
+    bool WheelIsGrounded(int wheel) const;
+    /// Set maximum suspension travel value.
+    void SetMaxSuspensionTravel(int wheel, float maxSuspensionTravel);
+    /// Set wheel direction vector.
+    void SetWheelDirection(int wheel, Vector3 direction);
+    /// Set wheel axle vector.
+    void SetWheelAxle(int wheel, Vector3 axle);
+    /// Set side speed which is considered sliding.
+    void SetMaxSideSlipSpeed(float speed);
+    /// Set cumulative skid info.
+    void SetWheelSkidInfoCumulative(int wheel, float skid);
+    /// Set revolution per minute value for when wheel doesn't touch ground. If set to 0 (or not set), calculated from engine force (probably not what you want).
+    void SetInAirRPM(float rpm);
+    /// Init the vehicle component after creation
+    void Init();
+    /// Perform fixed step pre-update.
+    void FixedUpdate(float timeStep);
+    /// Perform fixed step post-update.
+    void FixedPostUpdate(float timeStep);
+    /// Perform variable step post-update.
+    void PostUpdate(float timeStep);
+
+    /// Get wheel position relative to RigidBody.
+    Vector3 GetWheelPosition(int wheel);
+    /// Get wheel rotation relative to RigidBody.
+    Quaternion GetWheelRotation(int wheel);
+    /// Get wheel connection point relative to RigidBody.
+    Vector3 GetWheelConnectionPoint(int wheel) const;
+    /// Get number of attached wheels.
+    int GetNumWheels() const;
+    /// Get node of the wheel.
+    Node *GetWheelNode(int wheel) const;
+    /// Get steering value of particular wheel.
+    float GetSteeringValue(int wheel) const;
+    /// Get suspension stiffness for particular wheel.
+    float GetWheelSuspensionStiffness(int wheel) const;
+    /// Get wheel damping relaxation.
+    float GetWheelDampingRelaxation(int wheel) const;
+    /// Get wheel damping compression.
+    float GetWheelDampingCompression(int wheel) const;
+    /// Get wheel friction slip.
+    float GetWheelFrictionSlip(int wheel) const;
+    /// Get wheel roll influence.
+    float GetWheelRollInfluence(int wheel) const;
+    /// Get engine force for the wheel.
+    float GetEngineForce(int wheel) const;
+    /// Get hand brake value.
+    float GetBrake(int wheel) const;
+    /// Get wheel radius.
+    float GetWheelRadius(int wheel) const;
+    /// Get wheel rest length.
+    void SetWheelRestLength(int wheel, float length);
+    /// Get wheel rest length.
+    float GetWheelRestLength(int wheel) const;
+    /// Get maximum suspension travel value.
+    float GetMaxSuspensionTravel(int wheel);
+    /// Get wheel axle vector.
+    Vector3 GetWheelAxle(int wheel) const;
+    /// Get wheel slide speed.
+    float GetWheelSideSlipSpeed(int wheel) const;
+    /// Get side speed which is considered sliding.
+    float GetMaxSideSlipSpeed() const;
+    /// Sliding factor 0 <= x <= 1.
+    float GetWheelSkidInfo(int wheel) const;
+    /// Get wheel direction vector.
+    Vector3 GetWheelDirection(int wheel) const;
+    /// Get cumulative skid info.
+    float GetWheelSkidInfoCumulative(int wheel) const;
+    /// True if front wheel, otherwise false.
+    bool IsFrontWheel(int wheel) const;
+    /// Get wheel contact position.
+    Vector3 GetContactPosition(int wheel) const;
+    /// Get contact normal.
+    Vector3 GetContactNormal(int wheel) const;
+    /// Get revolution per minute value for when wheel doesn't touch ground.
+    float GetInAirRPM() const;
+
+    /// Get wheel data attribute for serialization.
+    VariantVector GetWheelDataAttr() const;
+    /// Set wheel data attribute during loading.
+    void SetWheelDataAttr(const VariantVector& value);
+
+private:
+    /// If the RigidBody should be activated.
+    bool activate_;
+    /// Hull RigidBody
+    WeakPtr<RigidBody> hullBody_;
+    /// Opaque Bullet data hidden from public
+    RaycastVehicleData *vehicleData_;
+    /// Nodes of all wheels
+    Vector<Node*> wheelNodes_;
+    /// All wheels original rotations. These are applied in addition to wheel rotations by btRaycastVehicle
+    Vector<Quaternion> origRotation_;
+    /// Revolutions per minute value for in-air motor wheels. FIXME: set this one per wheel
+    float inAirRPM_;
+    /// Per-wheel extra settings.
+    Vector<float> skidInfoCumulative_;
+    /// Wheel side movement speed.
+    Vector<float> wheelSideSlipSpeed_;
+    /// Side slip speed threshold.
+    float maxSideSlipSpeed_;
+    /// Loaded data temporarily wait here for ApplyAttributes to come pick them up.
+    VariantVector loadedWheelData_;
+};
 
-    void RegisterRaycastVehicleLibrary(Context* context);
 }

+ 1 - 1
bin/Data/Scripts/46_RaycastVehicleDemo.as

@@ -270,7 +270,7 @@ HandlePostUpdate(StringHash eventType, VariantMap& eventData)
     float cameraRayLength = (cameraTargetPos - cameraStartPos).length;
     PhysicsRaycastResult result =
         scene_.physicsWorld.RaycastSingle(cameraRay, cameraRayLength, 2);
-    if (result.body ! is null)
+    if (result.body !is null)
         cameraTargetPos =
             cameraStartPos + cameraRay.direction * (result.distance - 0.5f);
     cameraNode.position = cameraTargetPos;