From ed7262c14fce4c3b9b005e605b1a7991a58c662d Mon Sep 17 00:00:00 2001 From: Hipstercat Date: Fri, 17 Apr 2020 17:39:48 +0200 Subject: [PATCH] added object management --- 3d.gd | 31 +++++ 3d.tscn | 69 +++++++---- MeshInstance.gd | 14 ++- model.gd | 28 +++++ modelitem.gd | 23 ++++ objectmanager.gd | 280 +++++++++++++++++++++++++++++++++++++++++++++ player/Player.tscn | 4 +- 7 files changed, 417 insertions(+), 32 deletions(-) create mode 100644 model.gd create mode 100644 modelitem.gd create mode 100644 objectmanager.gd diff --git a/3d.gd b/3d.gd index 00da6ae..5715544 100644 --- a/3d.gd +++ b/3d.gd @@ -12,10 +12,37 @@ onready var camera = get_node("Player/Head/Camera") ################################################## +func create_water(): + # create water + var waterscene = load("res://realistic_water_shader/water.tscn") + for x in range(-1000,1000, 128): + for y in range(-1000,1000, 128): + var water_instance = waterscene.instance() + water_instance.transform.origin.x = x + water_instance.transform.origin.y = 0 + water_instance.transform.origin.z = y + add_child(water_instance) + func _ready() -> void: if fast_close: print("** Fast Close enabled in the 's_main.gd' script **") print("** 'Esc' to close 'Shift + F1' to release mouse **") + var giantsscript = load("res://objectmanager.gd") + var objmgr = giantsscript.ObjectManager.new() + # var giants_dir_browser = FileDialog.new() + # giants_dir_browser.mode = FileDialog.MODE_OPEN_DIR + # giants_dir_browser.window_title = "Select your Giants directory" + # giants_dir_browser.access = FileDialog.ACCESS_FILESYSTEM + # add_child(giants_dir_browser) + # giants_dir_browser.popup_centered() + objmgr.build() + var m = objmgr.load_model("W_story1_rock_2.gbs") + # print(m.tex) + # print(m.point_uv) + print(m.tex) + var meshinstance = objmgr.load_model_mesh(m) + meshinstance.transform.origin.y = 50 + add_child(meshinstance) func _input(event: InputEvent) -> void: @@ -40,3 +67,7 @@ func _process(delta): func _on_Button_pressed(): get_tree().quit() + + +func _on_GiantsDirectory_dir_selected(dir): + pass # Replace with function body. diff --git a/3d.tscn b/3d.tscn index 48c8398..de1920b 100644 --- a/3d.tscn +++ b/3d.tscn @@ -1,20 +1,35 @@ -[gd_scene load_steps=8 format=2] +[gd_scene load_steps=9 format=2] [ext_resource path="res://player/Player.tscn" type="PackedScene" id=1] [ext_resource path="res://MeshInstance.tscn" type="PackedScene" id=2] [ext_resource path="res://3d.gd" type="Script" id=3] -[ext_resource path="res://ImmediateGeometry.gd" type="Script" id=4] -[ext_resource path="res://Water.tscn" type="PackedScene" id=5] -[sub_resource type="SpatialMaterial" id=7] +[sub_resource type="SpatialMaterial" id=1] vertex_color_use_as_albedo = true params_cull_mode = 2 -[sub_resource type="SpatialMaterial" id=6] -vertex_color_use_as_albedo = true -params_diffuse_mode = 4 -params_specular_mode = 4 -params_cull_mode = 2 +[sub_resource type="ProceduralSky" id=2] +sky_top_color = Color( 0.00392157, 0.235294, 0.360784, 1 ) +sky_horizon_color = Color( 0.0117647, 0.482353, 0.980392, 1 ) +ground_bottom_color = Color( 0.0431373, 0.509804, 0.980392, 1 ) +ground_horizon_color = Color( 0.0117647, 0.482353, 0.980392, 1 ) +ground_energy = 1.5 +sun_color = Color( 0.686275, 0.196078, 0.00392157, 1 ) +sun_longitude = 180.0 +sun_energy = 2.0 + +[sub_resource type="Environment" id=3] +background_mode = 2 +background_sky = SubResource( 2 ) +background_color = Color( 0.0627451, 0.541176, 0.772549, 1 ) +auto_exposure_speed = 2.0 + +[sub_resource type="CubeMesh" id=4] +size = Vector3( 5000, 2, 5000 ) + +[sub_resource type="SpatialMaterial" id=5] +flags_transparent = true +albedo_color = Color( 0, 0.882353, 1, 0.0313726 ) [node name="Spatial" type="Spatial"] script = ExtResource( 3 ) @@ -23,7 +38,7 @@ script = ExtResource( 3 ) transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0.151, 200, -0.003 ) [node name="GiantsTerrain" parent="." instance=ExtResource( 2 )] -material_override = SubResource( 7 ) +material_override = SubResource( 1 ) [node name="Label" type="Label" parent="."] margin_right = 40.0 @@ -32,19 +47,6 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="DirectionalLight" type="DirectionalLight" parent="."] -transform = Transform( 1, 0, 0, 0, -0.00790628, 0.999969, 0, -0.999969, -0.00790628, 0, 300, 0 ) -light_energy = 1.94 -shadow_enabled = true - -[node name="ImmediateGeometry" type="ImmediateGeometry" parent="."] -material_override = SubResource( 6 ) -cast_shadow = 0 -script = ExtResource( 4 ) - -[node name="Water" parent="." instance=ExtResource( 5 )] -transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -10, 0 ) - [node name="Button" type="Button" parent="."] margin_top = 579.365 margin_right = 40.0 @@ -53,4 +55,25 @@ text = "Quit" __meta__ = { "_edit_use_anchors_": false } + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = SubResource( 3 ) + +[node name="MyWater" type="MeshInstance" parent="."] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -10, 0 ) +visible = false +mesh = SubResource( 4 ) +material/0 = SubResource( 5 ) + +[node name="GiantsDirectory" type="FileDialog" parent="."] +margin_right = 307.0 +margin_bottom = 130.0 +popup_exclusive = true +window_title = "Open Giants directory" +resizable = true +mode = 2 +access = 2 +current_dir = "/home/tasty/Jeux/GiantsEdit" +current_path = "/home/tasty/Jeux/GiantsEdit/" [connection signal="pressed" from="Button" to="." method="_on_Button_pressed"] +[connection signal="dir_selected" from="GiantsDirectory" to="." method="_on_GiantsDirectory_dir_selected"] diff --git a/MeshInstance.gd b/MeshInstance.gd index 2609875..2e1bc8c 100644 --- a/MeshInstance.gd +++ b/MeshInstance.gd @@ -6,6 +6,7 @@ var xoffset var yoffset var minheight var maxheight +var heightscale var xverticesnumber var yverticesnumber var stretch @@ -37,9 +38,8 @@ func _on_MeshInstance_ready(): mesh = m func fill(): - print("version="+str(version)) # fill read values - print("fill") + # print("fill") var p = 0 while p < xverticesnumber * yverticesnumber: var b = file.get_8() @@ -54,13 +54,13 @@ func fill(): if p >= xverticesnumber * yverticesnumber: return if version != 7: - vertices[p][2] = file.get_float() # height + vertices[p][2] = file.get_float() * heightscale # height vertices[p][3] = file.get_8() # triangulation vertices[p][4] = file.get_8() # R vertices[p][5] = file.get_8() # G vertices[p][6] = file.get_8() # B else: - vertices[p][2] = file.get_float() # height + vertices[p][2] = file.get_float() * heightscale # height vertices[p][3] = file.get_8() # triangulation vertices[p][4] = file.get_8() # R vertices[p][5] = file.get_8() # G @@ -84,6 +84,8 @@ func readgti(filename): xverticesnumber = file.get_32() yverticesnumber = file.get_32() stretch = file.get_float() + stretch = 40.0 + heightscale = stretch/40.0 # normal stretch u1 = file.get_float() u2 = file.get_float() u3 = file.get_float() @@ -97,7 +99,7 @@ func readgti(filename): vertices.resize(xverticesnumber * yverticesnumber) # initialize empty terrain - print("init") + # print("init") for y in range(yverticesnumber): for x in range(xverticesnumber): vertices[y * xverticesnumber + x] = [] @@ -114,7 +116,7 @@ func readgti(filename): file.close() # sort triangles - print("sort") + # print("sort") var i = 0 # triangles.resize(2*len(vertices)) for y in range(yverticesnumber-1): diff --git a/model.gd b/model.gd new file mode 100644 index 0000000..f01028a --- /dev/null +++ b/model.gd @@ -0,0 +1,28 @@ +extends Node + +class Model: + var magic + var u1 + var basepoints + var basepoint = [] + var texpos + var vertexrefs + var vertexref = [] + var points + var point_1 = [] + var point_2 = [] + var point_uv = [] + var point_c = [] + var ref1 = [] + var u2 + var u3 + var u4 + var u5 + var u6 + var u7 + var part = [] + var tex = [] + var parts + var bounds1 + var bounds2 + var maxbound diff --git a/modelitem.gd b/modelitem.gd new file mode 100644 index 0000000..b978216 --- /dev/null +++ b/modelitem.gd @@ -0,0 +1,23 @@ +extends Node + +class ModelItem: + var objname + var objindex + var refs + var wordz + var refs_ + + var refstart + var refnum + var texture + var bumptexture + var falloff + var blend + var flags + var emissive + var ambiant + var diffuse + var specular + var power + + var triangle = [] diff --git a/objectmanager.gd b/objectmanager.gd new file mode 100644 index 0000000..09df983 --- /dev/null +++ b/objectmanager.gd @@ -0,0 +1,280 @@ +extends Node + +class ObjectManager: + var GIANTS_PATH = "/home/tasty/Jeux/Giants Citizen Kabuto" + var index = {} + + func build() -> void: + var bin_dir = Directory.new() + if bin_dir.open(GIANTS_PATH+"/Bin") == OK: + bin_dir.list_dir_begin() + var file_name = bin_dir.get_next() + while (file_name != ""): + if not bin_dir.current_is_dir() and file_name.ends_with(".gzp"): + # print("Found GZP file: " + file_name) + var gzp_file = File.new() + gzp_file.open(GIANTS_PATH+"/Bin/"+file_name, File.READ) + read_gzp_to_indexes(gzp_file) + gzp_file.close() + file_name = bin_dir.get_next() + + func read_gzp_to_indexes(file: File) -> void: + var checksum = file.get_32() + assert(checksum == 0x6608F101) + var meta_info_offset = file.get_32() + file.seek(meta_info_offset) + var unk = file.get_32() + var entries_count = file.get_32() + for i in range(entries_count): + var compressed_size = file.get_32() + var original_size = file.get_32() + var file_time = file.get_32() + var content_offset = file.get_32() + 16 + var compression = file.get_8() + var name_length = file.get_8() + var name = file.get_buffer(name_length).get_string_from_ascii() + if name.ends_with(".tga") or name.ends_with(".gbs"): + index[name] = file.get_path_absolute() + # if name.ends_with(".gbs"): + # print(name) + + func read_file_in_gzp(filename: String) -> StreamPeerBuffer: + var gzp_file = index[filename] + var res = StreamPeerBuffer.new() + var file = File.new() + if not file.open(gzp_file, File.READ) == OK: + print("Could not open "+filename) + return res + var checksum = file.get_32() + assert(checksum == 0x6608F101) + var meta_info_offset = file.get_32() + file.seek(meta_info_offset) + var unk = file.get_32() + var entries_count = file.get_32() + for i in range(entries_count): + var compressed_size = file.get_32() + var original_size = file.get_32() + var file_time = file.get_32() + var content_offset = file.get_32() + 16 + var compression = file.get_8() + var name_length = file.get_8() + var name = file.get_buffer(name_length).get_string_from_ascii() + if name == filename: + var current_offset = file.get_position() + file.seek(content_offset) + var data = file.get_buffer(compressed_size) + file.seek(current_offset) + if compression == 1: + data = _decompress(data, original_size) + res.data_array = data + file.close() + return res + + func load_model(gbs_file: String): + var pos = 0 + var gbs_stream = read_file_in_gzp(gbs_file) + var model = load("res://model.gd").Model.new() + var modelitem_gd = load("res://modelitem.gd") + model.magic = gbs_stream.get_32() + model.u1 = gbs_stream.get_32() + model.basepoints = gbs_stream.get_32() + print("basepoints="+str(model.basepoints)) + model.basepoint = [] + model.basepoint.resize(model.basepoints) + for s in range(model.basepoints): + var x = gbs_stream.get_float() + var y = gbs_stream.get_float() + var z = gbs_stream.get_float() + model.basepoint[s] = [x, y, z] + + if model.u1 == 7: + model.texpos = gbs_stream.get_32() + model.vertexrefs = gbs_stream.get_32() + model.vertexref.resize(model.vertexrefs) + for s in range(model.vertexrefs): + model.vertexref[s] = gbs_stream.get_16() + + model.points = gbs_stream.get_32() + model.point_1.resize(model.points) + print("points="+str(model.points)) + if model.u1 == 7: + model.point_2.resize(model.points) + model.point_uv.resize(model.points) + # model.point_c.resize(model.points*3) + for s in range(model.points): + model.point_1[s] = gbs_stream.get_16() + if model.u1 == 7: + for s in range(model.points): + model.point_2[s] = gbs_stream.get_16() + for s in range(model.points): + model.point_uv[s] = [] + model.point_uv[s].resize(2) + model.point_uv[s][0] = gbs_stream.get_float() + model.point_uv[s][1] = gbs_stream.get_float() + + for s in range(model.points): + var r = gbs_stream.get_8() + var g = gbs_stream.get_8() + var b = gbs_stream.get_8() + model.point_c.append(r) + model.point_c.append(g) + model.point_c.append(b) + + var i = gbs_stream.get_32() + print("i="+str(i)) + model.ref1.resize(i) + for s in range(i): + model.ref1[s] = [] + model.ref1[s].resize(5) + model.ref1[s][0] = gbs_stream.get_32() + model.ref1[s][1] = gbs_stream.get_32() + model.ref1[s][2] = gbs_stream.get_32() + model.ref1[s][3] = gbs_stream.get_32() + model.ref1[s][4] = gbs_stream.get_32() + + model.parts = gbs_stream.get_32() + print("parts="+str(model.parts)) + model.part.resize(model.parts) + for p in range(model.parts): + model.part[p] = modelitem_gd.ModelItem.new() + model.part[p].objname = gbs_stream.get_string(32) + print("Objname: "+model.part[p].objname) + model.part[p].objindex = gbs_stream.get_32() + model.part[p].refs = gbs_stream.get_32() + model.part[p].wordz = gbs_stream.get_32() + model.part[p].refs_ = gbs_stream.get_16() + model.part[p].triangle.resize(model.part[p].refs) + for s in range(model.part[p].refs): + model.part[p].triangle[s] = [] + model.part[p].triangle[s].resize(3) + model.part[p].triangle[s][0] = gbs_stream.get_16() + model.part[p].triangle[s][1] = gbs_stream.get_16() + model.part[p].triangle[s][2] = gbs_stream.get_16() + model.part[p].refstart = gbs_stream.get_32() + model.part[p].refnum = gbs_stream.get_32() + model.part[p].texture = gbs_stream.get_string(32) + model.part[p].bumptexture = gbs_stream.get_string(32) + model.part[p].falloff = gbs_stream.get_float() + model.part[p].blend = gbs_stream.get_float() + model.part[p].flags = gbs_stream.get_32() + model.part[p].emissive = gbs_stream.get_32() + model.part[p].ambiant = gbs_stream.get_32() + model.part[p].diffuse = gbs_stream.get_32() + model.part[p].specular = gbs_stream.get_32() + model.part[p].power = gbs_stream.get_float() + model.tex.resize(model.parts) + for s in range(model.parts): + if model.part[s].texture != "": + model.tex[s] = load_texture(model.part[s].texture+".tga") + else: + model.tex[s] = null + + model.bounds1 = model.basepoint[0] + model.bounds2 = model.basepoint[0] + model.maxbound = 0 + for s in range(model.basepoints): + var r = sqrt(pow(model.basepoint[s][0], 2) + pow(model.basepoint[s][1], 2) + pow(model.basepoint[s][2], 2)) + if r > model.maxbound: + model.maxbound = r + + for s in range(model.basepoints): + if model.basepoint[s][0] < model.bounds1[0]: + model.bounds1[0] = model.basepoint[s][0] + if model.basepoint[s][1] < model.bounds1[1]: + model.bounds1[1] = model.basepoint[s][1] + if model.basepoint[s][2] < model.bounds1[2]: + model.bounds1[2] = model.basepoint[s][2] + + if model.basepoint[s][0] > model.bounds2[0]: + model.bounds2[0] = model.basepoint[s][0] + if model.basepoint[s][1] > model.bounds2[1]: + model.bounds2[1] = model.basepoint[s][1] + if model.basepoint[s][2] > model.bounds2[2]: + model.bounds2[2] = model.basepoint[s][2] + + return model + + func load_texture(texture_file: String) -> ImageTexture: + print("Loading texture "+texture_file) + var tmpDirectory = Directory.new() + if not tmpDirectory.dir_exists("res://tmp"): + tmpDirectory.make_dir("res://tmp") + var stream = read_file_in_gzp(texture_file) + var tmpFile = File.new() + tmpFile.open("res://tmp/"+texture_file, File.WRITE) + tmpFile.store_buffer(stream.data_array) + print("Saved to: "+tmpFile.get_path_absolute()) + tmpFile.close() + var img = Image.new() + var tex = ImageTexture.new() + img.load("res://tmp/"+texture_file) + tex.create_from_image(img) + # tmpDirectory.remove("res://tmp/"+texture_file) + return tex + + func load_model_mesh(model) -> MeshInstance: + var meshinstance = MeshInstance.new() + var mesh = Mesh.new() + for i in range(model.parts): + var st = SurfaceTool.new() + st.begin(Mesh.PRIMITIVE_TRIANGLES) + var mat = SpatialMaterial.new() + mat.params_cull_mode = SpatialMaterial.CULL_DISABLED + if model.tex[i]: + mat.albedo_texture = model.tex[i] + st.set_material(mat) + + assert(len(model.basepoint) % 3 == 0) + + for j in range(len(model.part[i].triangle)): + for k in range(2): + var l = model.part[i].triangle[j][k] + st.add_uv(Vector2(model.point_uv[l][0], model.point_uv[l][1])) + st.add_color(Color( + model.point_c[l*3+0] / 255.0 + (model.part[i].diffuse & 255) / 255.0, + model.point_c[l*3+1] / 255.0 + ((model.part[i].diffuse >> 8) & 255) / 255.0, + model.point_c[l*3+2] / 255.0 + ((model.part[i].diffuse >> 16) & 255) / 255.0)) + l = model.point_1[l] + st.add_vertex(Vector3( + model.basepoint[l][0], + model.basepoint[l][1], + model.basepoint[l][2])) + mesh = st.commit(mesh) + meshinstance.mesh = mesh + return meshinstance + + func _decompress(compressed_bytes: PoolByteArray, original_size: int) -> PoolByteArray: + var i = 0 + var j = 0 + var dec_byte = 0 + var dec_bits = 8 + var buff_start = 0xFEE + + var res = PoolByteArray() + res.resize(original_size) + if (original_size == 0): + return res + + while j < original_size: + if dec_bits == 8: + dec_byte = compressed_bytes[i] + i+=1 + dec_bits = 0 + if (dec_byte >> dec_bits & 1) == 0: + var dec_pos = ((compressed_bytes[i] + ((compressed_bytes[i + 1] & 0xF0) << 4) - buff_start - j) & 0xFFF) - 0x1000 + j + var dec_len = (compressed_bytes[i + 1] & 0xF) + 3 + i+=2 + while dec_len > 0: + if dec_pos >= 0: + res[j] = res[dec_pos] + else: + res[j] = 32 + j+=1 + dec_pos += 1 + dec_len -= 1 + else: + res[j] = compressed_bytes[i] + i+=1 + j+=1 + dec_bits += 1 + return res diff --git a/player/Player.tscn b/player/Player.tscn index 9e8945b..385eabb 100644 --- a/player/Player.tscn +++ b/player/Player.tscn @@ -1,7 +1,6 @@ -[gd_scene load_steps=4 format=2] +[gd_scene load_steps=3 format=2] [ext_resource path="res://player/player_controller.gd" type="Script" id=1] -[ext_resource path="res://default_env.tres" type="Environment" id=2] [sub_resource type="CapsuleShape" id=1] radius = 0.6 @@ -24,6 +23,5 @@ shape = SubResource( 1 ) transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0 ) [node name="Camera" type="Camera" parent="Head"] -environment = ExtResource( 2 ) fov = 80.0 far = 10000.0