restructure the repository
This commit is contained in:
parent
63230b7754
commit
936acf8703
12 changed files with 9 additions and 344 deletions
22
Notes.md
22
Notes.md
|
@ -1,22 +0,0 @@
|
||||||
# Resources
|
|
||||||
|
|
||||||
- [vrpn-rs description of VRPN protocol](https://github.com/vrpn/vrpn-rs/blob/main/Protocol.md)
|
|
||||||
|
|
||||||
# Design
|
|
||||||
|
|
||||||
Allow for a session based design - data needs to be collected per block
|
|
||||||
and immediatly made available. Minimal or no internal state keeping!
|
|
||||||
|
|
||||||
- first collect names and ids of message_types and senders (stored in session)
|
|
||||||
- register listeners in session
|
|
||||||
- listeners inject captured data with signals
|
|
||||||
|
|
||||||
- keep naming "classic" ??? ... above session is a tracker with a sender with sensors
|
|
||||||
|
|
||||||
# Todo
|
|
||||||
- Testset for Quaternion rotations
|
|
||||||
- Axis as subscene
|
|
||||||
|
|
||||||
# Internal Notes
|
|
||||||
|
|
||||||
- Graphics Interaction Lab OptiTrack system is at 212.201.64.122
|
|
197
VRPN.gd
197
VRPN.gd
|
@ -1,197 +0,0 @@
|
||||||
extends Node
|
|
||||||
class_name VRPN
|
|
||||||
|
|
||||||
# tracking associated data
|
|
||||||
enum TrackingData { POS_QUAT, VELOCITY, ACCELERATION }
|
|
||||||
|
|
||||||
# magic cookie
|
|
||||||
const magic_cookie_start : String = "vrpn: ver."
|
|
||||||
# kinda redundant as we take the seq number as well
|
|
||||||
static var header_size : int = aligned_size(20)
|
|
||||||
|
|
||||||
|
|
||||||
var sensors : Dictionary[int,String] = {}
|
|
||||||
var messages : Dictionary[int,String] = {}
|
|
||||||
|
|
||||||
signal connected(s:StreamPeerTCP)
|
|
||||||
signal data(data:Array)
|
|
||||||
signal disconnected
|
|
||||||
signal error
|
|
||||||
|
|
||||||
@export var tracker_receivers : Array[VRPN_Receiver] = []
|
|
||||||
|
|
||||||
@onready var _stream: StreamPeerTCP = StreamPeerTCP.new()
|
|
||||||
|
|
||||||
@export var vrpn_server : String = "127.0.0.1"
|
|
||||||
@export var vrpn_port : int = 3883
|
|
||||||
|
|
||||||
func _ready() -> void:
|
|
||||||
|
|
||||||
self.connect_to_host(vrpn_server,vrpn_port)
|
|
||||||
|
|
||||||
if not connected.has_connections():
|
|
||||||
connected.connect(self._on_connected)
|
|
||||||
if not data.has_connections():
|
|
||||||
data.connect(self._on_data)
|
|
||||||
if not disconnected.has_connections():
|
|
||||||
disconnected.connect(self._on_disconnected)
|
|
||||||
if not error.has_connections():
|
|
||||||
error.connect(self._on_error)
|
|
||||||
|
|
||||||
func _process(delta: float) -> void:
|
|
||||||
var old_status = _stream.get_status()
|
|
||||||
_stream.poll()
|
|
||||||
var new_status = _stream.get_status()
|
|
||||||
if old_status != new_status:
|
|
||||||
match new_status:
|
|
||||||
_stream.STATUS_NONE:
|
|
||||||
emit_signal("disconnected")
|
|
||||||
_stream.STATUS_CONNECTING:
|
|
||||||
print("Connecting.")
|
|
||||||
_stream.STATUS_CONNECTED:
|
|
||||||
print("Connected.")
|
|
||||||
emit_signal("connected",_stream.poll()
|
|
||||||
)
|
|
||||||
_stream.STATUS_ERROR:
|
|
||||||
print("Error with socket stream.")
|
|
||||||
emit_signal("error")
|
|
||||||
|
|
||||||
if new_status == _stream.STATUS_CONNECTED:
|
|
||||||
var available_bytes: int = _stream.get_available_bytes()
|
|
||||||
if available_bytes > 0:
|
|
||||||
var res = _stream.get_partial_data(available_bytes)
|
|
||||||
if res[0] != OK:
|
|
||||||
emit_signal("error")
|
|
||||||
else:
|
|
||||||
emit_signal("data", res[1])
|
|
||||||
|
|
||||||
func connect_to_host(host: String, port: int) -> void:
|
|
||||||
print("Connecting to %s:%d" % [host, port])
|
|
||||||
if _stream.connect_to_host(host, port) != OK:
|
|
||||||
print("Error connecting to host.")
|
|
||||||
emit_signal("error")
|
|
||||||
|
|
||||||
func send(data: PackedByteArray) -> bool:
|
|
||||||
if _stream.get_status() != _stream.STATUS_CONNECTED:
|
|
||||||
print("Error: Stream is not currently connected.")
|
|
||||||
return false
|
|
||||||
var error: int = _stream.put_data(data)
|
|
||||||
if error != OK:
|
|
||||||
print("Error writing to stream: ", error)
|
|
||||||
return false
|
|
||||||
return true
|
|
||||||
|
|
||||||
|
|
||||||
func _on_data(data : Array):
|
|
||||||
var bytes = PackedByteArray(data)
|
|
||||||
var as_cookie = bytes.get_string_from_ascii()
|
|
||||||
|
|
||||||
# Cookie Hack!
|
|
||||||
if as_cookie.begins_with(VRPN.magic_cookie_start): #
|
|
||||||
# kaboom we just send back the same cookie :)
|
|
||||||
self.send(bytes)
|
|
||||||
else:
|
|
||||||
VRPN.marshall_block(bytes,self)
|
|
||||||
|
|
||||||
|
|
||||||
func _on_connected(s : StreamPeerTCP):
|
|
||||||
print("Connected to",s.get_connected_host()) # Replace with function body.
|
|
||||||
|
|
||||||
func _on_disconnected():
|
|
||||||
print("Disconnected") # Replace with function body.
|
|
||||||
|
|
||||||
func _on_error():
|
|
||||||
print("Error") # Replace with function body.
|
|
||||||
|
|
||||||
|
|
||||||
static func marshall_block(data : PackedByteArray,session : VRPN) -> void:
|
|
||||||
|
|
||||||
# need to fix that
|
|
||||||
var block_offset : int = 0
|
|
||||||
|
|
||||||
while data.size() > block_offset:
|
|
||||||
# reader for stream
|
|
||||||
var header := StreamPeerBuffer.new()
|
|
||||||
# get block addresses
|
|
||||||
header.data_array = data.slice(block_offset,block_offset+header_size)
|
|
||||||
# make sure we read as big endian
|
|
||||||
header.big_endian = true
|
|
||||||
|
|
||||||
# read header
|
|
||||||
var length := header.get_32() as int # length of message
|
|
||||||
var time_sec := header.get_32() as int # datetime sec
|
|
||||||
var time_msec := header.get_32() as int # datetime micro sec
|
|
||||||
var sender_id := header.get_32() as int # sender id
|
|
||||||
var message_type := header.get_32() as int # type of message (payload)
|
|
||||||
var sequence_num := header.get_32() as int # inofficial sequence number (padding)
|
|
||||||
|
|
||||||
if false:
|
|
||||||
print("length '%d'" % length)
|
|
||||||
print("time_sec '%d'" % time_sec)
|
|
||||||
print("time_msec '%d'" % time_msec)
|
|
||||||
print("sender_id '%d'" % sender_id)
|
|
||||||
print("message_type '%d'" % message_type)
|
|
||||||
print("sequence_num '%d'" % sequence_num)
|
|
||||||
|
|
||||||
marshall_body(data.slice(block_offset+header_size,block_offset+length),message_type,sender_id,session)
|
|
||||||
|
|
||||||
# next datablock
|
|
||||||
block_offset += aligned_size(length)
|
|
||||||
|
|
||||||
static func decode_string(stream : StreamPeerBuffer) -> String:
|
|
||||||
var len = stream.get_32()
|
|
||||||
return stream.get_string(len)
|
|
||||||
|
|
||||||
|
|
||||||
static func marshall_body(data : PackedByteArray,message_type : int, sender_id: int, session : VRPN):
|
|
||||||
var body := StreamPeerBuffer.new()
|
|
||||||
body.data_array = data
|
|
||||||
body.big_endian = true
|
|
||||||
|
|
||||||
# only take message_type directly for negative (-1,-2)
|
|
||||||
# messages that provide dynamic descriptors
|
|
||||||
if message_type < 0:
|
|
||||||
# message and sender descriptions
|
|
||||||
match message_type:
|
|
||||||
-1: # sensor names
|
|
||||||
var name = decode_string(body)
|
|
||||||
print("sensor name is '%s' with '%d" % [name,sender_id])
|
|
||||||
session.sensors[sender_id] = name
|
|
||||||
-2: # message names
|
|
||||||
var name = decode_string(body)
|
|
||||||
print("message name is '%s' for message_type '%d'" % [name,sender_id])
|
|
||||||
session.messages[sender_id] = name
|
|
||||||
return
|
|
||||||
|
|
||||||
# now we use the string identifiers
|
|
||||||
# because they are supposedly dynamically assigned
|
|
||||||
match session.messages[message_type]:
|
|
||||||
'vrpn_Tracker Pos_Quat': # quat pos
|
|
||||||
# get id
|
|
||||||
var sensor_id = body.get_32()
|
|
||||||
var padding = body.get_32() # padding
|
|
||||||
var pos = Vector3(body.get_double(),body.get_double(),body.get_double())
|
|
||||||
# VRPN quaternions are w,xyz
|
|
||||||
var quat_w = body.get_double()
|
|
||||||
var quat_x = body.get_double()
|
|
||||||
var quat_y = body.get_double()
|
|
||||||
var quat_z = body.get_double()
|
|
||||||
#var quat = Quaternion(quat_x,quat_y,quat_z,quat_w).normalized()
|
|
||||||
# bug? Documentation of Godot Quaternion c'tor is x,y,x,w
|
|
||||||
# but implementation follow classic w,x,y,z order
|
|
||||||
var quat = Quaternion(quat_w,quat_x,quat_y,quat_z).normalized()
|
|
||||||
|
|
||||||
for r in session.tracker_receivers:
|
|
||||||
r._on_pos_quat({
|
|
||||||
"tracker" : session.sensors[sender_id],
|
|
||||||
"sensor" : sensor_id,
|
|
||||||
"position" : pos,
|
|
||||||
"rotation" : quat
|
|
||||||
})
|
|
||||||
_:
|
|
||||||
pass
|
|
||||||
#print("unhandled message type {0}".format([message_type]))
|
|
||||||
|
|
||||||
|
|
||||||
static func aligned_size(actual_size : int, alignment : int = 8) -> int:
|
|
||||||
return (actual_size + alignment - 1) & ~(alignment - 1)
|
|
|
@ -1 +0,0 @@
|
||||||
uid://dmq3i7qmo1qe0
|
|
|
@ -1,17 +0,0 @@
|
||||||
extends Node3D
|
|
||||||
|
|
||||||
class_name VRPN_Receiver
|
|
||||||
|
|
||||||
@export var tracker_name : String = "Tracker0"
|
|
||||||
@export var tracker_sensor : int = 0
|
|
||||||
@export var tracker_use_position : bool = true
|
|
||||||
@export var tracker_use_rotation : bool = true
|
|
||||||
|
|
||||||
func _on_pos_quat(tracker_data : Dictionary):
|
|
||||||
|
|
||||||
if tracker_data['tracker'] == tracker_name and tracker_data['sensor'] == tracker_sensor:
|
|
||||||
if tracker_use_position:
|
|
||||||
self.global_position = tracker_data['position']
|
|
||||||
if tracker_use_rotation:
|
|
||||||
var rotation := tracker_data['rotation'] as Quaternion
|
|
||||||
self.global_basis = Basis(rotation)
|
|
|
@ -1 +0,0 @@
|
||||||
uid://dpj1wrvfsiq4v
|
|
|
@ -1,8 +1,8 @@
|
||||||
[gd_scene load_steps=5 format=3 uid="uid://bj5ykdjle10tt"]
|
[gd_scene load_steps=5 format=3 uid="uid://bj5ykdjle10tt"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://dmq3i7qmo1qe0" path="res://VRPN.gd" id="2_24d08"]
|
[ext_resource type="Script" uid="uid://dmq3i7qmo1qe0" path="res://addons/vrpn/scripts/VRPN.gd" id="2_24d08"]
|
||||||
[ext_resource type="Script" uid="uid://dpj1wrvfsiq4v" path="res://VRPN_Receiver.gd" id="2_170dk"]
|
[ext_resource type="Script" uid="uid://dpj1wrvfsiq4v" path="res://addons/vrpn/scripts/VRPN_Receiver.gd" id="2_170dk"]
|
||||||
[ext_resource type="PackedScene" uid="uid://b426fy7d6jw2d" path="res://axis.blend" id="3_170dk"]
|
[ext_resource type="PackedScene" uid="uid://b426fy7d6jw2d" path="res://addons/vrpn/assets/axis.blend" id="3_170dk"]
|
||||||
|
|
||||||
[sub_resource type="PlaneMesh" id="PlaneMesh_24d08"]
|
[sub_resource type="PlaneMesh" id="PlaneMesh_24d08"]
|
||||||
size = Vector2(6, 2)
|
size = Vector2(6, 2)
|
||||||
|
@ -21,9 +21,9 @@ shadow_enabled = true
|
||||||
[node name="VRPN" type="Node3D" parent="Root" node_paths=PackedStringArray("tracker_receivers")]
|
[node name="VRPN" type="Node3D" parent="Root" node_paths=PackedStringArray("tracker_receivers")]
|
||||||
script = ExtResource("2_24d08")
|
script = ExtResource("2_24d08")
|
||||||
tracker_receivers = [NodePath("RB1"), NodePath("RB2"), NodePath("../SpinTracker/Offset0/Tracker0"), NodePath("../SpinTracker/Tracker1"), NodePath("../SpinTracker/Offset2/Tracker2")]
|
tracker_receivers = [NodePath("RB1"), NodePath("RB2"), NodePath("../SpinTracker/Offset0/Tracker0"), NodePath("../SpinTracker/Tracker1"), NodePath("../SpinTracker/Offset2/Tracker2")]
|
||||||
vrpn_server = "212.201.64.122"
|
|
||||||
|
|
||||||
[node name="RB1" type="Node3D" parent="Root/VRPN"]
|
[node name="RB1" type="Node3D" parent="Root/VRPN"]
|
||||||
|
visible = false
|
||||||
script = ExtResource("2_170dk")
|
script = ExtResource("2_170dk")
|
||||||
tracker_name = "RB1"
|
tracker_name = "RB1"
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ tracker_name = "RB1"
|
||||||
transform = Transform3D(0.1, 0, 0, 0, 0.1, 0, 0, 0, 0.1, 0, 0, 0)
|
transform = Transform3D(0.1, 0, 0, 0, 0.1, 0, 0, 0, 0.1, 0, 0, 0)
|
||||||
|
|
||||||
[node name="RB2" type="Node3D" parent="Root/VRPN"]
|
[node name="RB2" type="Node3D" parent="Root/VRPN"]
|
||||||
|
visible = false
|
||||||
script = ExtResource("2_170dk")
|
script = ExtResource("2_170dk")
|
||||||
tracker_name = "RB2"
|
tracker_name = "RB2"
|
||||||
|
|
||||||
|
@ -46,11 +47,11 @@ mesh = SubResource("PlaneMesh_24d08")
|
||||||
|
|
||||||
[node name="SpinTracker" type="Node3D" parent="Root"]
|
[node name="SpinTracker" type="Node3D" parent="Root"]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.764802, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.764802, 0)
|
||||||
visible = false
|
|
||||||
|
|
||||||
[node name="Tracker1" type="Node3D" parent="Root/SpinTracker"]
|
[node name="Tracker1" type="Node3D" parent="Root/SpinTracker"]
|
||||||
script = ExtResource("2_170dk")
|
script = ExtResource("2_170dk")
|
||||||
tracker_name = "Tracker1"
|
tracker_name = "Tracker1"
|
||||||
|
tracker_use_position = false
|
||||||
|
|
||||||
[node name="axis2" parent="Root/SpinTracker/Tracker1" instance=ExtResource("3_170dk")]
|
[node name="axis2" parent="Root/SpinTracker/Tracker1" instance=ExtResource("3_170dk")]
|
||||||
transform = Transform3D(0.1, 0, 0, 0, 0.1, 0, 0, 0, 0.1, 0, 0, 0)
|
transform = Transform3D(0.1, 0, 0, 0, 0.1, 0, 0, 0, 0.1, 0, 0, 0)
|
||||||
|
@ -65,6 +66,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1, 0, 0)
|
||||||
[node name="Tracker2" type="Node3D" parent="Root/SpinTracker/Offset2"]
|
[node name="Tracker2" type="Node3D" parent="Root/SpinTracker/Offset2"]
|
||||||
script = ExtResource("2_170dk")
|
script = ExtResource("2_170dk")
|
||||||
tracker_name = "Tracker2"
|
tracker_name = "Tracker2"
|
||||||
|
tracker_use_position = false
|
||||||
|
|
||||||
[node name="axis" parent="Root/SpinTracker/Offset2/Tracker2" instance=ExtResource("3_170dk")]
|
[node name="axis" parent="Root/SpinTracker/Offset2/Tracker2" instance=ExtResource("3_170dk")]
|
||||||
transform = Transform3D(0.1, 0, 0, 0, 0.1, 0, 0, 0, 0.1, 0, 0, 0)
|
transform = Transform3D(0.1, 0, 0, 0, 0.1, 0, 0, 0, 0.1, 0, 0, 0)
|
||||||
|
@ -78,6 +80,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0)
|
||||||
|
|
||||||
[node name="Tracker0" type="Node3D" parent="Root/SpinTracker/Offset0"]
|
[node name="Tracker0" type="Node3D" parent="Root/SpinTracker/Offset0"]
|
||||||
script = ExtResource("2_170dk")
|
script = ExtResource("2_170dk")
|
||||||
|
tracker_use_position = false
|
||||||
|
|
||||||
[node name="axis" parent="Root/SpinTracker/Offset0/Tracker0" instance=ExtResource("3_170dk")]
|
[node name="axis" parent="Root/SpinTracker/Offset0/Tracker0" instance=ExtResource("3_170dk")]
|
||||||
transform = Transform3D(0.1, 0, 0, 0, 0.1, 0, 0, 0, 0.1, 0, 0, 0)
|
transform = Transform3D(0.1, 0, 0, 0, 0.1, 0, 0, 0, 0.1, 0, 0, 0)
|
BIN
axis.blend
BIN
axis.blend
Binary file not shown.
|
@ -1,62 +0,0 @@
|
||||||
[remap]
|
|
||||||
|
|
||||||
importer="scene"
|
|
||||||
importer_version=1
|
|
||||||
type="PackedScene"
|
|
||||||
uid="uid://b426fy7d6jw2d"
|
|
||||||
path="res://.godot/imported/axis.blend-5b7f41137e49e6b98e717dd423c9150b.scn"
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://axis.blend"
|
|
||||||
dest_files=["res://.godot/imported/axis.blend-5b7f41137e49e6b98e717dd423c9150b.scn"]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
nodes/root_type=""
|
|
||||||
nodes/root_name=""
|
|
||||||
nodes/apply_root_scale=true
|
|
||||||
nodes/root_scale=1.0
|
|
||||||
nodes/import_as_skeleton_bones=false
|
|
||||||
nodes/use_node_type_suffixes=true
|
|
||||||
meshes/ensure_tangents=true
|
|
||||||
meshes/generate_lods=true
|
|
||||||
meshes/create_shadow_meshes=true
|
|
||||||
meshes/light_baking=1
|
|
||||||
meshes/lightmap_texel_size=0.2
|
|
||||||
meshes/force_disable_compression=false
|
|
||||||
skins/use_named_skins=true
|
|
||||||
animation/import=true
|
|
||||||
animation/fps=30
|
|
||||||
animation/trimming=false
|
|
||||||
animation/remove_immutable_tracks=true
|
|
||||||
animation/import_rest_as_RESET=false
|
|
||||||
import_script/path=""
|
|
||||||
_subresources={
|
|
||||||
"nodes": {
|
|
||||||
"PATH:Camera": {
|
|
||||||
"import/skip_import": true
|
|
||||||
},
|
|
||||||
"PATH:Light": {
|
|
||||||
"import/skip_import": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
blender/nodes/visible=0
|
|
||||||
blender/nodes/active_collection_only=false
|
|
||||||
blender/nodes/punctual_lights=true
|
|
||||||
blender/nodes/cameras=true
|
|
||||||
blender/nodes/custom_properties=true
|
|
||||||
blender/nodes/modifiers=1
|
|
||||||
blender/meshes/colors=false
|
|
||||||
blender/meshes/uvs=true
|
|
||||||
blender/meshes/normals=true
|
|
||||||
blender/meshes/export_geometry_nodes_instances=false
|
|
||||||
blender/meshes/tangents=true
|
|
||||||
blender/meshes/skins=2
|
|
||||||
blender/meshes/export_bones_deforming_mesh_only=false
|
|
||||||
blender/materials/unpack_enabled=true
|
|
||||||
blender/materials/export_materials=1
|
|
||||||
blender/animation/limit_playback=true
|
|
||||||
blender/animation/always_sample=true
|
|
||||||
blender/animation/group_tracks=true
|
|
1
icon.svg
1
icon.svg
|
@ -1 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><rect width="124" height="124" x="2" y="2" fill="#363d52" stroke="#212532" stroke-width="4" rx="14"/><g fill="#fff" transform="translate(12.322 12.322)scale(.101)"><path d="M105 673v33q407 354 814 0v-33z"/><path fill="#478cbf" d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 814 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H446l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z"/><path d="M483 600c0 34 58 34 58 0v-86c0-34-58-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042" transform="translate(12.322 12.322)scale(.101)"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></svg>
|
|
Before Width: | Height: | Size: 994 B |
|
@ -1,37 +0,0 @@
|
||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="CompressedTexture2D"
|
|
||||||
uid="uid://cdprcmtx102rp"
|
|
||||||
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://icon.svg"
|
|
||||||
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/high_quality=false
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_compression=1
|
|
||||||
compress/normal_map=0
|
|
||||||
compress/channel_pack=0
|
|
||||||
mipmaps/generate=false
|
|
||||||
mipmaps/limit=-1
|
|
||||||
roughness/mode=0
|
|
||||||
roughness/src_normal=""
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
process/hdr_as_srgb=false
|
|
||||||
process/hdr_clamp_exposure=false
|
|
||||||
process/size_limit=0
|
|
||||||
detect_3d/compress_to=1
|
|
||||||
svg/scale=1.0
|
|
||||||
editor/scale_with_editor_scale=false
|
|
||||||
editor/convert_colors_with_editor_theme=false
|
|
|
@ -13,4 +13,4 @@ config_version=5
|
||||||
config/name="uvrpn"
|
config/name="uvrpn"
|
||||||
run/main_scene="uid://bj5ykdjle10tt"
|
run/main_scene="uid://bj5ykdjle10tt"
|
||||||
config/features=PackedStringArray("4.4", "Forward Plus")
|
config/features=PackedStringArray("4.4", "Forward Plus")
|
||||||
config/icon="res://icon.svg"
|
config/icon="uid://cdprcmtx102rp"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue