Skip to content

Commit 8d604aa

Browse files
Adding mesh view scene
1 parent ba3056f commit 8d604aa

3 files changed

Lines changed: 132 additions & 0 deletions

File tree

scenes/MeshView.tscn

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[gd_scene format=3 uid="uid://w8375y4hfvw0"]
2+
3+
[ext_resource type="Script" uid="uid://dusuxv2yqo31o" path="res://scripts/mesh_loader.gd" id="1_4ebgs"]
4+
[ext_resource type="Script" uid="uid://demefs1tns4yw" path="res://addons/goutte.camera.trackball/trackball_camera.gd" id="2_ae8pf"]
5+
[ext_resource type="Shader" uid="uid://dojlkwvd3613r" path="res://shaders/eye_light.gdshader" id="2_xp361"]
6+
7+
[sub_resource type="ShaderMaterial" id="ShaderMaterial_r74bk"]
8+
render_priority = 0
9+
shader = ExtResource("2_xp361")
10+
shader_parameter/albedo = Color(0, 0.735357, 0, 1)
11+
shader_parameter/shininess = 24.0
12+
13+
[node name="MeshView" type="Node3D" unique_id=2065950553]
14+
15+
[node name="MeshInstance3D" type="MeshInstance3D" parent="." unique_id=279862154]
16+
script = ExtResource("1_4ebgs")
17+
material = SubResource("ShaderMaterial_r74bk")
18+
19+
[node name="TrackballCamera" type="Camera3D" parent="." unique_id=419741164]
20+
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 5)
21+
script = ExtResource("2_ae8pf")
22+
zoom_strength = 5.0
23+
zoom_maximum = 1000.0
24+
metadata/_custom_type_script = "uid://demefs1tns4yw"

scripts/mesh_loader.gd

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
extends MeshInstance3D
2+
3+
@export
4+
var material: ShaderMaterial
5+
6+
@onready var camera = $"../TrackballCamera"
7+
8+
func _ready() -> void:
9+
var test_path := "res://assets/Archicrop.obj"
10+
var imported_mesh = load_obj_at_runtime(test_path)
11+
if imported_mesh:
12+
self.mesh = imported_mesh
13+
self.mesh.surface_set_material(0, material)
14+
update_camera_position()
15+
else:
16+
print("Error reading OBJ file")
17+
18+
func update_camera_position():
19+
var max_position = self.mesh.get_aabb().get_longest_axis_size()
20+
var initial_position = camera.position
21+
camera.position = Vector3(initial_position.x,initial_position.y,max_position)
22+
23+
func load_obj_at_runtime(file_path: String) -> ArrayMesh:
24+
var file = FileAccess.open(file_path, FileAccess.READ)
25+
if not file: return
26+
var text = file.get_as_text()
27+
file.close()
28+
29+
var vertices: PackedVector3Array = []
30+
var uvs: PackedVector2Array = []
31+
var normals: PackedVector3Array = []
32+
33+
var st = SurfaceTool.new()
34+
st.begin(Mesh.PRIMITIVE_TRIANGLES)
35+
36+
var lines = text.split("\n")
37+
for line in lines:
38+
line = line.strip_edges()
39+
if line.is_empty() or line.begins_with("#"):
40+
continue
41+
42+
var parts = line.split(" ", false)
43+
var line_type = parts[0]
44+
45+
match line_type:
46+
"v": # Position
47+
vertices.append(Vector3(float(parts[1]), float(parts[2]), float(parts[3])))
48+
"vt": # UVs
49+
# OBJ Y-axis for UVs is inverted compared to Godot
50+
uvs.append(Vector2(float(parts[1]), 1.0 - float(parts[2])))
51+
"vn": # Normal
52+
normals.append(Vector3(float(parts[1]), float(parts[2]), float(parts[3])))
53+
"f": # Faces
54+
if parts.size() == 4:
55+
_add_face_vertex(parts[1], vertices, uvs, normals, st)
56+
_add_face_vertex(parts[2], vertices, uvs, normals, st)
57+
_add_face_vertex(parts[3], vertices, uvs, normals, st)
58+
elif parts.size() == 5:
59+
_add_face_vertex(parts[1], vertices, uvs, normals, st)
60+
_add_face_vertex(parts[2], vertices, uvs, normals, st)
61+
_add_face_vertex(parts[3], vertices, uvs, normals, st)
62+
63+
_add_face_vertex(parts[1], vertices, uvs, normals, st)
64+
_add_face_vertex(parts[3], vertices, uvs, normals, st)
65+
_add_face_vertex(parts[4], vertices, uvs, normals, st)
66+
67+
if normals.is_empty():
68+
st.generate_normals()
69+
if not uvs.is_empty():
70+
st.generate_tangents()
71+
72+
return st.commit()
73+
74+
func _add_face_vertex(token: String, vertices: PackedVector3Array, uvs: PackedVector2Array, normals: PackedVector3Array, st: SurfaceTool) -> void:
75+
var indices = token.split("/")
76+
if indices.size() > 1 and not indices[1].is_empty():
77+
var uv_index = int(indices[1]) - 1
78+
if uv_index < uvs.size():
79+
st.set_uv(uvs[uv_index])
80+
81+
if indices.size() > 2 and not indices[2].is_empty():
82+
var normal_index = int(indices[2]) - 1
83+
if normal_index < normals.size():
84+
st.set_normal(normals[normal_index])
85+
86+
var vertex_index = int(indices[0]) - 1
87+
if vertex_index < vertices.size():
88+
st.add_vertex(vertices[vertex_index])

shaders/eye_light.gdshader

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
shader_type spatial;
2+
render_mode blend_mix, depth_draw_opaque, cull_disabled, unshaded;
3+
4+
uniform vec4 albedo : source_color = vec4(1.0);
5+
uniform float shininess = 0.24;
6+
7+
void fragment() {
8+
vec3 camera_dir = vec3(0.0, 0.0, 1.0);
9+
vec3 view_normal = normalize((VIEW_MATRIX * vec4(NORMAL, 0.0)).xyz);
10+
11+
if (!FRONT_FACING) {
12+
view_normal = -view_normal;
13+
}
14+
15+
float diffuse = max(dot(view_normal, camera_dir), 0.0);
16+
float specular = pow(max(dot(view_normal, camera_dir), 0.0), shininess);
17+
vec3 final_color = (albedo.rgb * diffuse) + vec3(specular * 0.4);
18+
19+
ALBEDO = final_color;
20+
}

0 commit comments

Comments
 (0)