-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from aaronfranke/omi_vehicle
Add OMI_vehicle_* implementation and test files
- Loading branch information
Showing
86 changed files
with
6,578 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
# Godot 4+ specific ignores | ||
.godot/ | ||
*.uid | ||
|
||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
addons/omi_extensions/physics_gravity/global_gravity_setter.gd
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
class_name GlobalGravitySetter | ||
extends Node | ||
|
||
|
||
@export var gravity: float = 9.80665 | ||
@export var direction: Vector3 = Vector3.DOWN | ||
|
||
|
||
func _ready() -> void: | ||
var world_space_rid: RID = get_viewport().find_world_3d().space | ||
PhysicsServer3D.area_set_param(world_space_rid, PhysicsServer3D.AREA_PARAM_GRAVITY, gravity) | ||
PhysicsServer3D.area_set_param(world_space_rid, PhysicsServer3D.AREA_PARAM_GRAVITY_VECTOR, direction) | ||
queue_free() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
@tool | ||
class_name GLTFVehicleBody | ||
extends Resource | ||
|
||
|
||
## The input value controlling the ratio of the vehicle's angular forces. | ||
@export var angular_activation := Vector3.ZERO | ||
## The input value controlling the ratio of the vehicle's linear forces. | ||
@export var linear_activation := Vector3.ZERO | ||
## The gyroscope torque intrinsic to the vehicle, excluding torque from parts, measured in Newton-meters per radian (kg⋅m²/s²/rad). | ||
@export_custom(PROPERTY_HINT_NONE, "suffix:kg\u22C5m\u00B2/s\u00B2/rad (N\u22C5m/rad)") | ||
var gyroscope_torque := Vector3.ZERO | ||
## If non-negative, the speed in meters per second at which the vehicle should stop driving acceleration further. | ||
@export var max_speed: float = -1.0 | ||
## The index of the `OMI_seat` glTF node to use as the pilot / driver seat. | ||
@export var pilot_seat_index: int = -1 | ||
## The Godot node to use as the pilot seat / driver seat. | ||
var pilot_seat_node: Node3D = null | ||
## If true, the vehicle should slow its rotation down when not given angular activation input for a specific rotation. | ||
@export var angular_dampeners: bool = true | ||
## If true, the vehicle should slow itself down when not given linear activation input for a specific direction. | ||
@export var linear_dampeners: bool = false | ||
## If true, the vehicle should use a throttle for linear movement. If max_speed is non-negative, the throttle should be a ratio of that speed, otherwise it should be a ratio of thrust power. | ||
@export var use_throttle: bool = false | ||
|
||
|
||
static func from_node(vehicle_node: VehicleBody3D) -> GLTFVehicleBody: | ||
var ret := GLTFVehicleBody.new() | ||
if vehicle_node is PilotedVehicleBody3D: | ||
ret.angular_activation = vehicle_node.angular_activation | ||
ret.linear_activation = vehicle_node.linear_activation | ||
ret.gyroscope_torque = vehicle_node.gyroscope_torque | ||
ret.max_speed = vehicle_node.max_speed | ||
ret.pilot_seat_node = vehicle_node.pilot_seat_node | ||
ret.angular_dampeners = vehicle_node.angular_dampeners | ||
ret.linear_dampeners = vehicle_node.linear_dampeners | ||
ret.use_throttle = vehicle_node.use_throttle | ||
return ret | ||
|
||
|
||
func to_node(gltf_state: GLTFState, gltf_node: GLTFNode) -> PilotedVehicleBody3D: | ||
# Set up the body node. | ||
var vehicle_node := PilotedVehicleBody3D.new() | ||
var gltf_physics_body: GLTFPhysicsBody = gltf_node.get_additional_data(&"GLTFPhysicsBody") | ||
if gltf_physics_body == null: | ||
printerr("GLTF vehicle body: Expected the vehicle body to also be a physics body. Continuing anyway.") | ||
else: | ||
vehicle_node.mass = gltf_physics_body.mass | ||
vehicle_node.linear_velocity = gltf_physics_body.linear_velocity | ||
vehicle_node.angular_velocity = gltf_physics_body.angular_velocity | ||
vehicle_node.inertia = gltf_physics_body.inertia_diagonal | ||
vehicle_node.center_of_mass = gltf_physics_body.center_of_mass | ||
vehicle_node.center_of_mass_mode = RigidBody3D.CENTER_OF_MASS_MODE_CUSTOM | ||
# If there is a collider shape, set it up. | ||
var gltf_collider_shape: GLTFPhysicsShape = gltf_node.get_additional_data(&"GLTFPhysicsColliderShape") | ||
if gltf_collider_shape != null: | ||
_setup_shape_mesh_resource_from_index_if_needed(gltf_state, gltf_collider_shape) | ||
var col_shape: CollisionShape3D = gltf_collider_shape.to_node(true) | ||
col_shape.name = gltf_node.resource_name + "Collider" | ||
vehicle_node.add_child(col_shape) | ||
# Set up the vehicle properties. | ||
vehicle_node.angular_activation = angular_activation | ||
vehicle_node.linear_activation = linear_activation | ||
vehicle_node.gyroscope_torque = gyroscope_torque | ||
vehicle_node.max_speed = max_speed | ||
vehicle_node.angular_dampeners = angular_dampeners | ||
vehicle_node.linear_dampeners = linear_dampeners | ||
vehicle_node.use_throttle = use_throttle | ||
return vehicle_node | ||
|
||
|
||
static func from_dictionary(dict: Dictionary) -> GLTFVehicleBody: | ||
var ret := GLTFVehicleBody.new() | ||
if dict.has("angularActivation"): | ||
var ang_arr: Array = dict["angularActivation"] | ||
ret.angular_activation = Vector3(ang_arr[0], ang_arr[1], ang_arr[2]) | ||
if dict.has("linearActivation"): | ||
var lin_arr: Array = dict["linearActivation"] | ||
ret.linear_activation = Vector3(lin_arr[0], lin_arr[1], lin_arr[2]) | ||
if dict.has("gyroTorque"): | ||
var gyro_arr: Array = dict["gyroTorque"] | ||
ret.gyroscope_torque = Vector3(gyro_arr[0], gyro_arr[1], gyro_arr[2]) | ||
if dict.has("maxSpeed"): | ||
ret.max_speed = dict["maxSpeed"] | ||
if dict.has("pilotSeat"): | ||
ret.pilot_seat_index = dict["pilotSeat"] | ||
if dict.has("angularDampeners"): | ||
ret.angular_dampeners = dict["angularDampeners"] | ||
if dict.has("linearDampeners"): | ||
ret.linear_dampeners = dict["linearDampeners"] | ||
if dict.has("useThrottle"): | ||
ret.use_throttle = dict["useThrottle"] | ||
return ret | ||
|
||
|
||
func to_dictionary() -> Dictionary: | ||
var ret: Dictionary = {} | ||
if angular_activation != Vector3.ZERO: | ||
ret["angularActivation"] = [angular_activation.x, angular_activation.y, angular_activation.z] | ||
if linear_activation != Vector3.ZERO: | ||
ret["linearActivation"] = [linear_activation.x, linear_activation.y, linear_activation.z] | ||
if gyroscope_torque != Vector3.ZERO: | ||
ret["gyroTorque"] = [gyroscope_torque.x, gyroscope_torque.y, gyroscope_torque.z] | ||
if max_speed != -1.0: | ||
ret["maxSpeed"] = max_speed | ||
if pilot_seat_index != -1: | ||
ret["pilotSeat"] = pilot_seat_index | ||
if not angular_dampeners: # Default is true. | ||
ret["angularDampeners"] = angular_dampeners | ||
if linear_dampeners: | ||
ret["linearDampeners"] = linear_dampeners | ||
if use_throttle: | ||
ret["useThrottle"] = use_throttle | ||
return ret | ||
|
||
|
||
func _setup_shape_mesh_resource_from_index_if_needed(gltf_state: GLTFState, gltf_shape: GLTFPhysicsShape) -> void: | ||
var shape_mesh_index: int = gltf_shape.mesh_index | ||
if shape_mesh_index == -1: | ||
return # No mesh for this shape. | ||
var importer_mesh: ImporterMesh = gltf_shape.importer_mesh | ||
if importer_mesh != null: | ||
return # The mesh resource is already set up. | ||
var state_meshes: Array[GLTFMesh] = gltf_state.meshes | ||
var gltf_mesh: GLTFMesh = state_meshes[shape_mesh_index] | ||
importer_mesh = gltf_mesh.mesh | ||
gltf_shape.importer_mesh = importer_mesh |
59 changes: 59 additions & 0 deletions
59
addons/omi_extensions/vehicle/gltf_vehicle_hover_thruster.gd
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
@tool | ||
class_name GLTFVehicleHoverThruster | ||
extends Resource | ||
|
||
|
||
## The ratio of the maximum hover energy the hover thruster is currently using for propulsion. | ||
@export_range(0.0, 1.0, 0.01) | ||
var current_hover_ratio: float = 0.0 | ||
## The ratio of the maximum gimbal angles the hover thruster is rotated to. The vector length may not be longer than 1.0. | ||
@export var current_gimbal_ratio := Vector2(0.0, 0.0) | ||
## The maximum hover energy in Newton-meters (N⋅m or kg⋅m²/s²) that the hover thruster can provide. | ||
@export_custom(PROPERTY_HINT_NONE, "suffix:kg\u22C5m\u00B2/s\u00B2 (N\u22C5m)") | ||
var max_hover_energy: float = 0.0 | ||
## The maximum angle the hover thruster can gimbal or rotate in radians. | ||
@export_custom(PROPERTY_HINT_NONE, "suffix:rad") | ||
var max_gimbal: float = 0.0 | ||
|
||
|
||
static func from_node(thruster_node: VehicleHoverThruster3D) -> GLTFVehicleHoverThruster: | ||
var ret := GLTFVehicleHoverThruster.new() | ||
ret.current_hover_ratio = thruster_node.current_hover_ratio | ||
ret.current_gimbal_ratio = thruster_node.current_gimbal_ratio | ||
ret.max_hover_energy = thruster_node.max_hover_energy | ||
ret.max_gimbal = thruster_node.max_gimbal | ||
return ret | ||
|
||
|
||
func to_node() -> VehicleHoverThruster3D: | ||
var thruster_node := VehicleHoverThruster3D.new() | ||
thruster_node.current_hover_ratio = current_hover_ratio | ||
thruster_node.current_gimbal_ratio = current_gimbal_ratio | ||
thruster_node.max_hover_energy = max_hover_energy | ||
thruster_node.max_gimbal = max_gimbal | ||
return thruster_node | ||
|
||
|
||
static func from_dictionary(dict: Dictionary) -> GLTFVehicleHoverThruster: | ||
var ret := GLTFVehicleHoverThruster.new() | ||
if dict.has("currentHoverRatio"): | ||
ret.current_force_ratio = dict["currentHoverRatio"] | ||
if dict.has("currentGimbalRatio"): | ||
ret.current_gimbal_ratio = dict["currentGimbalRatio"] | ||
if dict.has("maxHoverEnergy"): | ||
ret.max_hover_energy = dict["maxHoverEnergy"] | ||
if dict.has("maxGimbal"): | ||
ret.max_gimbal = dict["maxGimbal"] | ||
return ret | ||
|
||
|
||
func to_dictionary() -> Dictionary: | ||
var ret: Dictionary = {} | ||
ret["maxHoverEnergy"] = max_hover_energy | ||
if current_hover_ratio != 0.0: | ||
ret["currentHoverRatio"] = current_hover_ratio | ||
if current_gimbal_ratio != Vector2.ZERO: | ||
ret["currentGimbalRatio"] = current_gimbal_ratio | ||
if max_gimbal != 0.0: | ||
ret["maxGimbal"] = max_gimbal | ||
return ret |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
@tool | ||
class_name GLTFVehicleThruster | ||
extends Resource | ||
|
||
|
||
## The ratio of the maximum thrust force the thruster is currently using for propulsion. | ||
@export_range(0.0, 1.0, 0.01) | ||
var current_force_ratio: float = 0.0 | ||
## The ratio of the maximum gimbal angles the thruster is rotated to. The vector length may not be longer than 1.0. | ||
@export var current_gimbal_ratio := Vector2(0.0, 0.0) | ||
## The maximum thrust force in Newtons (kg⋅m/s²) that the thruster can provide. | ||
@export_custom(PROPERTY_HINT_NONE, "suffix:kg\u22C5m/s\u00B2 (N)") | ||
var max_force: float = 0.0 | ||
## The maximum angle the thruster can gimbal or rotate in radians. | ||
@export_custom(PROPERTY_HINT_NONE, "suffix:rad") | ||
var max_gimbal: float = 0.0 | ||
|
||
|
||
static func from_node(thruster_node: VehicleThruster3D) -> GLTFVehicleThruster: | ||
var ret := GLTFVehicleThruster.new() | ||
ret.current_force_ratio = thruster_node.current_force_ratio | ||
ret.current_gimbal_ratio = thruster_node.current_gimbal_ratio | ||
ret.max_force = thruster_node.max_force | ||
ret.max_gimbal = thruster_node.max_gimbal | ||
return ret | ||
|
||
|
||
func to_node() -> VehicleThruster3D: | ||
var thruster_node := VehicleThruster3D.new() | ||
thruster_node.current_force_ratio = current_force_ratio | ||
thruster_node.current_gimbal_ratio = current_gimbal_ratio | ||
thruster_node.max_force = max_force | ||
thruster_node.max_gimbal = max_gimbal | ||
return thruster_node | ||
|
||
|
||
static func from_dictionary(dict: Dictionary) -> GLTFVehicleThruster: | ||
var ret := GLTFVehicleThruster.new() | ||
if dict.has("currentForceRatio"): | ||
ret.current_force_ratio = dict["currentForceRatio"] | ||
if dict.has("currentGimbalRatio"): | ||
ret.current_gimbal_ratio = dict["currentGimbalRatio"] | ||
if dict.has("maxForce"): | ||
ret.max_force = dict["maxForce"] | ||
if dict.has("maxGimbal"): | ||
ret.max_gimbal = dict["maxGimbal"] | ||
return ret | ||
|
||
|
||
func to_dictionary() -> Dictionary: | ||
var ret: Dictionary = {} | ||
ret["maxForce"] = max_force | ||
if current_force_ratio != 0.0: | ||
ret["currentForceRatio"] = current_force_ratio | ||
if current_gimbal_ratio != Vector2.ZERO: | ||
ret["currentGimbalRatio"] = current_gimbal_ratio | ||
if max_gimbal != 0.0: | ||
ret["maxGimbal"] = max_gimbal | ||
return ret |
Oops, something went wrong.