Large update with mostly rewritten character subsystem
This commit is contained in:
BIN
proto2/tests/.character_mod_test.gd.swp
Normal file
BIN
proto2/tests/.character_mod_test.gd.swp
Normal file
Binary file not shown.
222
proto2/tests/character_mod_test.gd
Normal file
222
proto2/tests/character_mod_test.gd
Normal file
@@ -0,0 +1,222 @@
|
||||
extends Spatial
|
||||
|
||||
func get_mesh(base: Node, mesh_name: String) -> ArrayMesh:
|
||||
var queue = [base]
|
||||
var mesh: ArrayMesh
|
||||
while queue.size() > 0:
|
||||
var item = queue[0]
|
||||
queue.pop_front()
|
||||
if item is MeshInstance && item.name == mesh_name && item.mesh:
|
||||
mesh = item.mesh
|
||||
break
|
||||
for c in item.get_children():
|
||||
queue.push_back(c)
|
||||
return mesh
|
||||
func get_mi(base: Node, mesh_name: String) -> MeshInstance:
|
||||
var queue = [base]
|
||||
var mi: MeshInstance
|
||||
while queue.size() > 0:
|
||||
var item = queue[0]
|
||||
queue.pop_front()
|
||||
if item is MeshInstance && item.name == mesh_name && item.mesh:
|
||||
mi = item
|
||||
break
|
||||
for c in item.get_children():
|
||||
queue.push_back(c)
|
||||
return mi
|
||||
#var modset_body = ModifierSet.new()
|
||||
#var modset_top = ModifierSet.new()
|
||||
#var modset_panties = ModifierSet.new()
|
||||
|
||||
var body_mi
|
||||
var mesh_id
|
||||
var _characters = []
|
||||
var slots_female = ["body", "top", "panties"]
|
||||
var slots_male = ["body"]
|
||||
var helpers = {
|
||||
"body": "base",
|
||||
"top": "tights",
|
||||
"panties": "tights"
|
||||
}
|
||||
var data_male = {}
|
||||
var data_female = {}
|
||||
var cha_male
|
||||
var cha_female
|
||||
func _ready():
|
||||
seed(OS.get_unix_time())
|
||||
# var base_male = characters.characters[0].instance()
|
||||
# var base_female = characters.characters[1].instance()
|
||||
# var fd = File.new()
|
||||
# fd.open("characters/blendmaps.bin", File.READ);
|
||||
# cha_male = CharacterModifierSet.new()
|
||||
# cha_female = CharacterModifierSet.new()
|
||||
# cha_female.set_base_name("body")
|
||||
# cha_male.set_base_name("body")
|
||||
# for e in slots_female:
|
||||
# data_female[e] = {
|
||||
# "mod": cha_female.create(e)
|
||||
# }
|
||||
# data_female[e].mod.set_uv_index(1)
|
||||
# cha_female.set_helper(e, helpers[e])
|
||||
# for e in slots_male:
|
||||
# data_male[e] = {
|
||||
# "mod": cha_male.create(e)
|
||||
# }
|
||||
# data_male[e].mod.set_uv_index(1)
|
||||
# cha_male.set_helper(e, helpers[e])
|
||||
# cha_female.add_mesh_scene(base_female)
|
||||
# cha_male.add_mesh_scene(base_male)
|
||||
# var bcount = fd.get_32()
|
||||
# for f in range(bcount):
|
||||
# var pos = fd.get_position()
|
||||
# cha_female.load(fd)
|
||||
# fd.seek(pos)
|
||||
# cha_male.load(fd)
|
||||
# print("done")
|
||||
# # print(data["body"].mod.get_modifier_list())
|
||||
# fd.close()
|
||||
# cha_male.add_bone_modifier("head_scale", base_male, "head", Transform().scaled(Vector3(1.3, 1.3, 1.3)))
|
||||
# cha_female.add_bone_modifier("head_scale", base_female, "head", Transform().scaled(Vector3(1.3, 1.3, 1.3)))
|
||||
# cha_male.add_bone_modifier("head_up", base_male, "head", Transform().translated(Vector3(0.0, 0.3, 0.0)))
|
||||
# cha_female.add_bone_modifier("head_up", base_female, "head", Transform().translated(Vector3(0.0, 0.3, 0.0)))
|
||||
# cha_male.add_bone_modifier("shoulder_l_rot", base_male, "shoulder01_L", Transform().rotated(Vector3(1, 0, 0), 95 * PI / 360.0))
|
||||
# cha_female.add_bone_modifier("shoulder_l_rot", base_female, "shoulder01_L", Transform().rotated(Vector3(1, 0, 0), 95 * PI / 360.0))
|
||||
# cha_male.add_bone_modifier("height", base_male, "pelvis", Transform().scaled(Vector3(1.2, 1.2, 1.2)))
|
||||
# cha_female.add_bone_modifier("height", base_female, "pelvis", Transform().scaled(Vector3(1.2, 1.2, 1.2)))
|
||||
# cha_male.add_bone_modifier_symmetry("shoulder", base_male, "shoulder01_L", "shoulder01_R")
|
||||
# cha_female.add_bone_modifier_symmetry("shoulder", base_female, "shoulder01_L", "shoulder01_R")
|
||||
# var num = 4
|
||||
# for k in range(num):
|
||||
# if randf() > 0.5:
|
||||
# var c = characters.characters[1].instance()
|
||||
# add_child(c)
|
||||
# c.translation.x = float(k)* 0.9 + randf() * 0.2 - float(num) * 0.9 * 0.5
|
||||
# c.translation.z = 5.0
|
||||
# c.rotation.y = PI
|
||||
# var cdata = {}
|
||||
# var mesh_id = cha_female.add_work_mesh_scene(c)
|
||||
# cdata.scene = c
|
||||
# cdata.mesh_id = mesh_id
|
||||
# cdata.cha = cha_female
|
||||
# _characters.push_back(cdata)
|
||||
# else:
|
||||
# var c = characters.characters[0].instance()
|
||||
# add_child(c)
|
||||
# c.translation.x = float(k) * 0.9 + randf() * 0.2 - float(num) * 0.9 * 0.5
|
||||
# c.translation.z = 5.0
|
||||
# c.rotation.y = PI
|
||||
# var cdata = {}
|
||||
# var mesh_id = cha_male.add_work_mesh_scene(c)
|
||||
# cdata.scene = c
|
||||
# cdata.mesh_id = mesh_id
|
||||
# cdata.cha = cha_male
|
||||
# _characters.push_back(cdata)
|
||||
$Camera.translation.x = -8.0
|
||||
$Camera.fov = 50.0
|
||||
var change_delay = 0.1
|
||||
var mod_id = "neck_width"
|
||||
var mod_val = 0.0
|
||||
|
||||
var char_id = 0
|
||||
var char_dist = 1.0
|
||||
var timeout = 30.0
|
||||
|
||||
func _process(delta):
|
||||
var mdist = 10.0
|
||||
var farthest = -1
|
||||
for ie in range(_characters.size()):
|
||||
var e = _characters[ie]
|
||||
var cpos = e.scene.global_transform.origin
|
||||
var campos = $Camera.global_transform.origin
|
||||
if mdist > abs(cpos.x - campos.x):
|
||||
mdist = abs(cpos.x - campos.x)
|
||||
farthest = ie
|
||||
# if mdist > 3.0 && farthest >= 0:
|
||||
# var cf = _characters[farthest]
|
||||
# cf.cha.remove_work_mesh_scene(cf.mesh_id)
|
||||
# cf.scene.queue_free()
|
||||
# _characters.remove(farthest)
|
||||
var c
|
||||
var cdata = {}
|
||||
if char_dist >= 1.0:
|
||||
var can_spawn = true
|
||||
for mc in _characters:
|
||||
if abs(mc.scene.translation.x - $Camera.translation.x - 3.0) < 1.0:
|
||||
can_spawn = false
|
||||
break
|
||||
if can_spawn:
|
||||
var xform : = Transform()
|
||||
xform.origin.x = $Camera.translation.x + 3.0
|
||||
xform.origin.z = 5.0
|
||||
xform.basis = xform.basis.rotated(Vector3(0, 1, 0), PI)
|
||||
if randf() > 0.5:
|
||||
c = characters.spawn_character(1, xform)
|
||||
# c = characters.characters[1].instance()
|
||||
# add_child(c)
|
||||
# c.translation.x = $Camera.translation.x + 3.0
|
||||
# c.translation.z = 5.0
|
||||
# c.rotation.y = PI
|
||||
# var mesh_id = cha_female.add_work_mesh_scene(c)
|
||||
cdata.scene = c
|
||||
# cdata.mesh_id = mesh_id
|
||||
# cdata.cha = cha_female
|
||||
_characters.push_back(cdata)
|
||||
else:
|
||||
c = characters.spawn_character(1, xform)
|
||||
# c = characters.characters[0].instance()
|
||||
# add_child(c)
|
||||
# c.translation.x = $Camera.translation.x + 3.0
|
||||
# c.translation.z = 5.0
|
||||
# c.rotation.y = PI
|
||||
# var mesh_id = cha_male.add_work_mesh_scene(c)
|
||||
cdata.scene = c
|
||||
# cdata.mesh_id = mesh_id
|
||||
# cdata.cha = cha_male
|
||||
_characters.push_back(cdata)
|
||||
# var mod_name_list = cha_female.get_modifier_list()
|
||||
var mod_name_list = characters.get_modifier_list(c)
|
||||
for cset in range(160):
|
||||
var _mod_id = mod_name_list[randi() % mod_name_list.size()]
|
||||
var _mod_val = randf() - 0.5
|
||||
characters.set_modifier_value(cdata.scene, _mod_id, _mod_val)
|
||||
# cdata.cha.set_modifier_value(cdata.mesh_id, _mod_id, _mod_val)
|
||||
# cdata.cha.modify(cdata.scene)
|
||||
characters.update()
|
||||
char_dist = 0.0
|
||||
$Camera.translation.x += 0.25 * delta
|
||||
# if change_delay <= 0:
|
||||
# var mod_name_list = cha_female.get_modifier_list()
|
||||
# char_id = randi() % _characters.size()
|
||||
# mod_id = mod_name_list[randi() % mod_name_list.size()]
|
||||
# mod_val = randf() - 0.5
|
||||
# change_delay = 0.1
|
||||
# else:
|
||||
# change_delay -= delta
|
||||
# var cmod = _characters[char_id]
|
||||
# cmod.cha.set_modifier_value(cmod.mesh_id, mod_id, lerp(cmod.cha.get_modifier_value(cmod.mesh_id, mod_id), mod_val, 0.5))
|
||||
# cmod.cha.modify()
|
||||
|
||||
var remove_ids = []
|
||||
for ie in range(_characters.size()):
|
||||
var e = _characters[ie]
|
||||
if abs($Camera.translation.x + 3.0 - e.scene.translation.x) > 6.0:
|
||||
characters.remove(e.scene)
|
||||
# e.cha.remove_work_meshes(e.mesh_id)
|
||||
# e.scene.queue_free()
|
||||
remove_ids.push_back(ie)
|
||||
|
||||
# remove_ids.sort()
|
||||
# remove_ids.invert()
|
||||
for e in remove_ids:
|
||||
_characters.remove(e)
|
||||
char_dist += delta
|
||||
timeout -= delta
|
||||
if timeout <= 0.0:
|
||||
get_tree().quit()
|
||||
func _physics_process(delta):
|
||||
if $Camera.translation.x >= 8.0:
|
||||
$Camera.translation.x -= 16.0
|
||||
for cm in _characters:
|
||||
cm.scene.translation.x -=16.0
|
||||
char_dist = 1.0
|
||||
|
||||
36
proto2/tests/character_mod_test.tscn
Normal file
36
proto2/tests/character_mod_test.tscn
Normal file
@@ -0,0 +1,36 @@
|
||||
[gd_scene load_steps=5 format=2]
|
||||
|
||||
[ext_resource path="res://tests/character_mod_test.gd" type="Script" id=1]
|
||||
|
||||
[sub_resource type="BoxShape" id=1]
|
||||
extents = Vector3( 20, 0.1, 20 )
|
||||
|
||||
[sub_resource type="CubeMesh" id=2]
|
||||
size = Vector3( 40, 0.1, 40 )
|
||||
subdivide_width = 8
|
||||
subdivide_depth = 8
|
||||
|
||||
[sub_resource type="SpatialMaterial" id=3]
|
||||
metallic = 0.8
|
||||
roughness = 0.0
|
||||
|
||||
[node name="character_mod_test" type="Spatial"]
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="Camera" type="Camera" parent="."]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.2, 8 )
|
||||
|
||||
[node name="StaticBody" type="StaticBody" parent="."]
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape" parent="StaticBody"]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0 )
|
||||
shape = SubResource( 1 )
|
||||
|
||||
[node name="MeshInstance" type="MeshInstance" parent="."]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0 )
|
||||
mesh = SubResource( 2 )
|
||||
material/0 = SubResource( 3 )
|
||||
|
||||
[node name="DirectionalLight" type="DirectionalLight" parent="."]
|
||||
transform = Transform( 1, 0, 0, 0, 0.0871556, 0.996195, 0, -0.996195, 0.0871556, 0, 20, 0 )
|
||||
shadow_enabled = true
|
||||
1062
proto2/tests/clothes-test.escn.import
Normal file
1062
proto2/tests/clothes-test.escn.import
Normal file
File diff suppressed because it is too large
Load Diff
80
proto2/tests/clothes-test.gd
Normal file
80
proto2/tests/clothes-test.gd
Normal file
@@ -0,0 +1,80 @@
|
||||
extends Spatial
|
||||
|
||||
onready var layers = [$base, $panties, $pants]
|
||||
var pairs = [[0, 2], [1, 2], [0, 1]]
|
||||
var cache = []
|
||||
|
||||
func cache_data():
|
||||
for k in range(layers.size()):
|
||||
var arrays = layers[k].mesh.surface_get_arrays(0)
|
||||
var data = {}
|
||||
data.vertices = arrays[Mesh.ARRAY_VERTEX]
|
||||
data.normals = arrays[Mesh.ARRAY_NORMAL]
|
||||
data.indices = arrays[Mesh.ARRAY_INDEX]
|
||||
data.bs = layers[k].mesh.surface_get_blend_shape_arrays(0)
|
||||
data.mat = layers[k].get_surface_material(0)
|
||||
data.mesh_mat = layers[k].mesh.surface_get_material(0)
|
||||
data.shrunk = shrink_vertices(data.vertices, data.normals)
|
||||
data.aabb = layers[k].get_aabb().grow(0.02)
|
||||
|
||||
cache.push_back(data)
|
||||
|
||||
func update_meshes():
|
||||
for k in range(layers.size()):
|
||||
layers[k].hide()
|
||||
var arrays = layers[k].mesh.surface_get_arrays(0)
|
||||
arrays[Mesh.ARRAY_VERTEX] = cache[k].vertices
|
||||
layers[k].mesh.surface_remove(0)
|
||||
layers[k].mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays, cache[k].bs)
|
||||
layers[k].set_surface_material(0, cache[k].mat)
|
||||
layers[k].mesh.surface_set_material(0, cache[k].mesh_mat)
|
||||
layers[k].show()
|
||||
|
||||
func get_layer_vertices(layer: int) -> PoolVector3Array:
|
||||
return cache[layer].vertices
|
||||
func get_layer_normals(layer: int) -> PoolVector3Array:
|
||||
return cache[layer].normals
|
||||
func get_layer_triangles(layer: int) -> PoolIntArray:
|
||||
return cache[layer].indices
|
||||
func shrink_vertices(v: PoolVector3Array, n: PoolVector3Array) -> PoolVector3Array:
|
||||
var ret : = PoolVector3Array()
|
||||
ret.resize(v.size())
|
||||
for i in range(v.size()):
|
||||
ret[i] = v[i] - n[i].normalized() * 0.035
|
||||
return ret
|
||||
func triangle_check(layer_inner: int, layer_outer: int) -> PoolVector3Array:
|
||||
var start_time = OS.get_unix_time()
|
||||
var inner_verts = get_layer_vertices(layer_inner)
|
||||
var inner_normals = get_layer_normals(layer_inner)
|
||||
var inner_verts_shrunk = cache[layer_inner].shrunk
|
||||
var outer_verts = get_layer_vertices(layer_outer)
|
||||
var outer_triangles = get_layer_triangles(layer_outer)
|
||||
for pt in range(inner_verts.size()):
|
||||
if !cache[layer_outer].aabb.has_point(inner_verts_shrunk[pt]):
|
||||
continue
|
||||
for tri in range(0, outer_triangles.size(), 3):
|
||||
var ray_pos = inner_verts_shrunk[pt]
|
||||
var ray_dir = inner_verts[pt] - inner_verts_shrunk[pt]
|
||||
var r = Geometry.ray_intersects_triangle(ray_pos, ray_dir,
|
||||
outer_verts[outer_triangles[tri]],
|
||||
outer_verts[outer_triangles[tri + 1]],
|
||||
outer_verts[outer_triangles[tri + 2]])
|
||||
if r:
|
||||
var dst = inner_verts_shrunk[pt].distance_to(r)
|
||||
if dst <= 0.035:
|
||||
var ndist = clamp(dst / 0.035, 0.0, 1.0)
|
||||
print(r, " ", ndist)
|
||||
inner_verts[pt] = inner_verts_shrunk[pt].linear_interpolate(inner_verts[pt], ndist)
|
||||
var end_time = OS.get_unix_time()
|
||||
print(" triangle_check time: ", end_time - start_time)
|
||||
return inner_verts
|
||||
func update_layers(layer_inner: int, layer_outer: int):
|
||||
var verts = triangle_check(layer_inner, layer_outer)
|
||||
cache[layer_inner].vertices = verts
|
||||
func _ready():
|
||||
cache_data()
|
||||
for p in pairs:
|
||||
update_layers(p[0], p[1])
|
||||
# $panties.hide()
|
||||
# $pants.hide()
|
||||
update_meshes()
|
||||
32
proto2/tests/clothes-test.tscn
Normal file
32
proto2/tests/clothes-test.tscn
Normal file
@@ -0,0 +1,32 @@
|
||||
[gd_scene load_steps=7 format=2]
|
||||
|
||||
[ext_resource path="res://tests/clothes-test.escn" type="PackedScene" id=1]
|
||||
[ext_resource path="res://tests/clothes-test.gd" type="Script" id=2]
|
||||
|
||||
[sub_resource type="SpatialMaterial" id=1]
|
||||
albedo_color = Color( 0.207843, 0.807843, 0.286275, 1 )
|
||||
|
||||
[sub_resource type="SpatialMaterial" id=2]
|
||||
albedo_color = Color( 0.827451, 0.513726, 0.513726, 1 )
|
||||
|
||||
[sub_resource type="CubeMesh" id=3]
|
||||
|
||||
[sub_resource type="SpatialMaterial" id=4]
|
||||
albedo_color = Color( 0.176471, 0.733333, 0.745098, 1 )
|
||||
|
||||
[node name="clothes-test" instance=ExtResource( 1 )]
|
||||
script = ExtResource( 2 )
|
||||
|
||||
[node name="Camera" parent="." index="1"]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0.00116634, 1.00691, 1.43248 )
|
||||
|
||||
[node name="panties" parent="." index="3"]
|
||||
material/0 = SubResource( 1 )
|
||||
|
||||
[node name="pants" parent="." index="4"]
|
||||
material/0 = SubResource( 2 )
|
||||
|
||||
[node name="MeshInstance" type="MeshInstance" parent="." index="5"]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.759001, -1.82452 )
|
||||
mesh = SubResource( 3 )
|
||||
material/0 = SubResource( 4 )
|
||||
78
proto2/tests/linreg.gd
Normal file
78
proto2/tests/linreg.gd
Normal file
@@ -0,0 +1,78 @@
|
||||
extends Reference
|
||||
class_name LinReg
|
||||
|
||||
var data = []
|
||||
var m = []
|
||||
var b = []
|
||||
var errors = []
|
||||
var size = 30
|
||||
func _init():
|
||||
b.resize(size)
|
||||
m.resize(size)
|
||||
errors.resize(size)
|
||||
for j in range(size):
|
||||
b[j] = 0.0
|
||||
m[j] = 1.0
|
||||
print("hello linreg")
|
||||
func sample_x():
|
||||
var ret = []
|
||||
for k in range(size):
|
||||
ret.push_back(randf() * 2.0 - 1.0)
|
||||
return ret
|
||||
func iterate(delta):
|
||||
var x = sample_x()
|
||||
var y = 0.0
|
||||
for nx in x:
|
||||
y += nx * nx
|
||||
y /= size
|
||||
data.push_back([x, y])
|
||||
linearRegression_gd()
|
||||
# print(m)
|
||||
# print(b)
|
||||
print(errors)
|
||||
return false
|
||||
func linearRegression_sq():
|
||||
var xsum = []
|
||||
var num = []
|
||||
var den = []
|
||||
xsum.resize(size)
|
||||
num.resize(size)
|
||||
den.resize(size)
|
||||
for j in range(xsum.size()):
|
||||
xsum[j] = 0.0
|
||||
num[j] = 0.0
|
||||
den[j] = 0.0
|
||||
b[j] = 0.0
|
||||
m[j] = 1.0
|
||||
var ysum = 0.0
|
||||
for i in range(data.size()):
|
||||
for j in range(data[i][0].size()):
|
||||
xsum[j] += data[i][0][j]
|
||||
ysum += data[i][1]
|
||||
var xmean = []
|
||||
for j in range(xsum.size()):
|
||||
xmean.push_back(xsum[j] / data.size())
|
||||
var ymean = ysum / data.size()
|
||||
for i in range(data.size()):
|
||||
var x = data[i][0]
|
||||
var y = data[i][1]
|
||||
for j in range(x.size()):
|
||||
num[j] += (x[j] - xmean[j]) * (y - ymean)
|
||||
den[j] += (x[j] - xmean[j]) * (x[j] - xmean[j])
|
||||
for j in range(size):
|
||||
m[j] = num[j] / den[j]
|
||||
b[j] = ymean - m[j] * xmean[j]
|
||||
|
||||
var learning_rate = 0.15
|
||||
func linearRegression_gd():
|
||||
for e in range(30):
|
||||
for i in range(data.size()):
|
||||
var x = data[i][0]
|
||||
var y = data[i][1]
|
||||
for j in range(x.size()):
|
||||
var guess = m[j] * x[j] + b[j]
|
||||
var error = y - guess
|
||||
errors[j] = error
|
||||
m[j] += error * x[j] * learning_rate
|
||||
b[j] += error * learning_rate
|
||||
|
||||
10
proto2/tests/linreg_test.gd
Normal file
10
proto2/tests/linreg_test.gd
Normal file
@@ -0,0 +1,10 @@
|
||||
extends MainLoop
|
||||
|
||||
var pct
|
||||
|
||||
func _initialize():
|
||||
print("hello, world!")
|
||||
pct = LinReg.new()
|
||||
return
|
||||
func _iteration(delta):
|
||||
return pct.iterate(delta)
|
||||
184
proto2/tests/nn.gd
Normal file
184
proto2/tests/nn.gd
Normal file
@@ -0,0 +1,184 @@
|
||||
extends Reference
|
||||
class_name NeuralNetwork
|
||||
|
||||
class Matrix:
|
||||
var r
|
||||
var c
|
||||
var data = []
|
||||
func _init(rows, cols):
|
||||
r = rows
|
||||
c = cols
|
||||
data.resize(r * c)
|
||||
for i in range(r):
|
||||
for j in range(c):
|
||||
data[i * c + j] = 0.0
|
||||
func _s(row, col, value):
|
||||
data[row * c + col] = value
|
||||
func _g(row, col):
|
||||
return data[row * c + col]
|
||||
static func multiply(m1, m2):
|
||||
assert(m1.c == m2.r)
|
||||
var result = Matrix.new(m1.r, m2.c)
|
||||
for i in range(result.r):
|
||||
for j in range(result.c):
|
||||
var sum = 0.0
|
||||
for k in range(m1.c):
|
||||
sum += m1.data[i * m1.c + k] * m2.data[k * m2.c + j]
|
||||
result.data[i * result.c + j] = sum
|
||||
return result
|
||||
|
||||
func multiply_elementwise(val):
|
||||
if val is Matrix:
|
||||
for i in range(data.size()):
|
||||
data[i] *= val.data[i]
|
||||
else:
|
||||
for i in range(data.size()):
|
||||
data[i] *= val
|
||||
func add(val):
|
||||
if val is Matrix:
|
||||
for i in range(data.size()):
|
||||
data[i] += val.data[i]
|
||||
else:
|
||||
for i in range(data.size()):
|
||||
data[i] += val
|
||||
func randomize():
|
||||
for i in range(data.size()):
|
||||
data[i] = floor(randf() * 2.0 - 1.0)
|
||||
func transposed():
|
||||
var result = Matrix.new(c, r)
|
||||
for i in range(r):
|
||||
for j in range(c):
|
||||
result.data[j * result.c + i] = data[i * c + j]
|
||||
return result
|
||||
static func transpose(mat):
|
||||
var result = Matrix.new(mat.c, mat.r)
|
||||
for i in range(mat.r):
|
||||
for j in range(mat.c):
|
||||
result.data[j * result.c + i] = mat.data[i * mat.c + j]
|
||||
return result
|
||||
static func from_array(arr):
|
||||
var m = Matrix.new(arr.size(), 1)
|
||||
for i in range(m.data.size()):
|
||||
m.data[i] = arr[i]
|
||||
return m
|
||||
static func subtract(m1, m2):
|
||||
var result = Matrix.new(m1.r, m1.c)
|
||||
for e in range(m1.data.size()):
|
||||
result.data[e] = m1.data[e] - m2.data[e]
|
||||
return result
|
||||
func display():
|
||||
print("[")
|
||||
for i in range(r):
|
||||
var mat_row = "\t[ "
|
||||
for j in range(c):
|
||||
mat_row += str(data[i * c + j])
|
||||
if j < c - 1:
|
||||
mat_row += " "
|
||||
else:
|
||||
mat_row += " ]"
|
||||
print(mat_row)
|
||||
print("]")
|
||||
func map(obj, f):
|
||||
for e in range(data.size()):
|
||||
var val = obj.call(f, data[e])
|
||||
data[e] = val
|
||||
static func map_s(m, obj, f):
|
||||
var result = Matrix.new(m.r, m.c)
|
||||
for e in range(m.data.size()):
|
||||
var val = obj.call(f, m.data[e])
|
||||
result.data[e] = val
|
||||
return result
|
||||
func to_array():
|
||||
return data
|
||||
|
||||
|
||||
var input_nodes
|
||||
var hidden_nodes
|
||||
var output_nodes
|
||||
var weights_ih
|
||||
var weights_ho
|
||||
var bias_h
|
||||
var bias_o
|
||||
var learning_rate = 0.1
|
||||
# 3Blue1Brown
|
||||
func tst(data):
|
||||
return 1.0
|
||||
func sigmoid(x):
|
||||
return 1.0 / (1.0 + exp(-x))
|
||||
func dsigmoid(x):
|
||||
return x * (1.0 - x)
|
||||
func feedforward(inputs_array):
|
||||
# Hidden outputs
|
||||
var inputs = Matrix.from_array(inputs_array)
|
||||
var hidden = Matrix.multiply(weights_ih, inputs)
|
||||
hidden.add(bias_h)
|
||||
hidden.map(self, "sigmoid")
|
||||
|
||||
var output = Matrix.multiply(weights_ho, hidden)
|
||||
output.add(bias_o)
|
||||
output.map(self, "sigmoid")
|
||||
|
||||
return output.to_array()
|
||||
func train(inputs_array, targets_array):
|
||||
var inputs = Matrix.from_array(inputs_array)
|
||||
var hidden = Matrix.multiply(weights_ih, inputs)
|
||||
hidden.add(bias_h)
|
||||
hidden.map(self, "sigmoid")
|
||||
|
||||
var outputs = Matrix.multiply(weights_ho, hidden)
|
||||
outputs.add(bias_o)
|
||||
outputs.map(self, "sigmoid")
|
||||
|
||||
var targets = Matrix.from_array(targets_array)
|
||||
var output_errors = Matrix.subtract(targets, outputs)
|
||||
var gradients = Matrix.map_s(outputs, self, "dsigmoid")
|
||||
gradients.multiply_elementwise(output_errors)
|
||||
gradients.multiply_elementwise(learning_rate)
|
||||
|
||||
var hidden_T = Matrix.transpose(hidden)
|
||||
var weights_ho_deltas = Matrix.multiply(gradients, hidden_T)
|
||||
weights_ho.add(weights_ho_deltas)
|
||||
bias_o.add(gradients)
|
||||
|
||||
var who_t = Matrix.transpose(weights_ho)
|
||||
var hidden_errors = Matrix.multiply(who_t, output_errors)
|
||||
var hidden_gradients = Matrix.map_s(hidden, self, "dsigmoid")
|
||||
hidden_gradients.multiply_elementwise(hidden_errors)
|
||||
hidden_gradients.multiply_elementwise(learning_rate)
|
||||
var inputs_T = Matrix.transpose(inputs)
|
||||
var weights_ih_deltas = Matrix.multiply(hidden_gradients, inputs_T)
|
||||
weights_ih.add(weights_ih_deltas)
|
||||
bias_h.add(hidden_gradients)
|
||||
|
||||
|
||||
# outputs.display()
|
||||
# targets.display()
|
||||
# error.display()
|
||||
|
||||
func _init(numI, numH, numO):
|
||||
input_nodes = numI
|
||||
hidden_nodes = numH
|
||||
output_nodes = numO
|
||||
weights_ih = Matrix.new(hidden_nodes, input_nodes)
|
||||
weights_ho = Matrix.new(output_nodes, hidden_nodes)
|
||||
weights_ih.randomize()
|
||||
weights_ho.randomize()
|
||||
bias_h = Matrix.new(hidden_nodes, 1)
|
||||
bias_h.randomize()
|
||||
bias_o = Matrix.new(output_nodes, 1)
|
||||
bias_o.randomize()
|
||||
|
||||
|
||||
# var matrix = Matrix.new(3, 2)
|
||||
# matrix.randomize()
|
||||
# matrix.display()
|
||||
# var matrix2 = Matrix.new(2, 3)
|
||||
# matrix2.randomize()
|
||||
# matrix2.display()
|
||||
# var matrix3 = Matrix.multiply(matrix, matrix2)
|
||||
# matrix3.display()
|
||||
# Matrix.transpose(matrix3).display()
|
||||
# matrix3.map(self, "tst")
|
||||
# matrix3.display()
|
||||
|
||||
|
||||
28
proto2/tests/nn_test.gd
Normal file
28
proto2/tests/nn_test.gd
Normal file
@@ -0,0 +1,28 @@
|
||||
extends MainLoop
|
||||
|
||||
var nn
|
||||
var train_ds = [
|
||||
[1, 0, 1],
|
||||
[0, 1, 1],
|
||||
[0, 0, 0],
|
||||
[1, 1, 0]
|
||||
]
|
||||
func _initialize():
|
||||
print("hello, world!")
|
||||
nn = NeuralNetwork.new(2, 2, 1)
|
||||
# var o = nn.feedforward([1,2,3])
|
||||
# print(o)
|
||||
for k in range(10000):
|
||||
for k in range(train_ds.size()):
|
||||
var d = randi() % train_ds.size()
|
||||
var e = train_ds[d]
|
||||
var inputs = [e[0], e[1]]
|
||||
var targets = [e[2]]
|
||||
nn.train(inputs, targets)
|
||||
print(nn.feedforward([0, 0]))
|
||||
print(nn.feedforward([1, 0]))
|
||||
print(nn.feedforward([0, 1]))
|
||||
print(nn.feedforward([1, 1]))
|
||||
func _iteration(delta):
|
||||
return true
|
||||
|
||||
21
proto2/tests/perceptron.gd
Normal file
21
proto2/tests/perceptron.gd
Normal file
@@ -0,0 +1,21 @@
|
||||
extends Reference
|
||||
class_name Perceptron
|
||||
var weights = []
|
||||
var learning_rate = 0.15
|
||||
func _init():
|
||||
print("hello perceptron")
|
||||
weights.resize(3)
|
||||
for i in range(weights.size()):
|
||||
weights[i] = randf()
|
||||
func guess(inputs):
|
||||
var sum = 0.0
|
||||
for i in range(weights.size()):
|
||||
sum += inputs[i] * weights[i]
|
||||
var ret = sign(sum)
|
||||
return ret
|
||||
func train(inputs, target):
|
||||
var g = guess(inputs)
|
||||
var err = target - g
|
||||
for i in range(weights.size()):
|
||||
weights[i] += err * inputs[i] * learning_rate
|
||||
|
||||
34
proto2/tests/perceptron_test.gd
Normal file
34
proto2/tests/perceptron_test.gd
Normal file
@@ -0,0 +1,34 @@
|
||||
extends MainLoop
|
||||
|
||||
var pct
|
||||
var dataset
|
||||
|
||||
func build_training_set():
|
||||
var data = []
|
||||
for k in range(400000):
|
||||
var x = randf() * 2.0 - 1.0
|
||||
var y = randf() * 2.0 - 1.0
|
||||
var label = 0
|
||||
if x > y:
|
||||
label = 1
|
||||
else:
|
||||
label = -1
|
||||
data.push_back([x, y, label])
|
||||
return data
|
||||
|
||||
func _initialize():
|
||||
print("hello, world!")
|
||||
pct = Perceptron.new()
|
||||
dataset = build_training_set()
|
||||
for i in range(dataset.size()):
|
||||
var pt = dataset[i]
|
||||
pct.train([pt[0], pt[1], 1.0], pt[2])
|
||||
return
|
||||
func _iteration(delta):
|
||||
if dataset.size() == 0:
|
||||
return true
|
||||
var pt = dataset.pop_front()
|
||||
var output = pct.guess([pt[0], pt[1], 1.0])
|
||||
print(output, " / ", pt[2] - output)
|
||||
return false
|
||||
|
||||
5
proto2/tests/quit.gd
Normal file
5
proto2/tests/quit.gd
Normal file
@@ -0,0 +1,5 @@
|
||||
tool
|
||||
extends Node
|
||||
|
||||
func _ready():
|
||||
get_tree().quit()
|
||||
6
proto2/tests/quit.tscn
Normal file
6
proto2/tests/quit.tscn
Normal file
@@ -0,0 +1,6 @@
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://tests/quit.gd" type="Script" id=1]
|
||||
|
||||
[node name="quit" type="Node"]
|
||||
script = ExtResource( 1 )
|
||||
191
proto2/tests/test-collect-data.gd
Normal file
191
proto2/tests/test-collect-data.gd
Normal file
@@ -0,0 +1,191 @@
|
||||
extends Spatial
|
||||
|
||||
var ch
|
||||
|
||||
var current_data = {}
|
||||
var nn
|
||||
|
||||
func train(quality):
|
||||
var inputs = []
|
||||
var dk = current_data.keys()
|
||||
dk.sort()
|
||||
for k in dk:
|
||||
if k == "quality":
|
||||
continue
|
||||
inputs.push_back(current_data[k])
|
||||
nn.train(inputs, [quality])
|
||||
func guess():
|
||||
var inputs = []
|
||||
var dk = current_data.keys()
|
||||
dk.sort()
|
||||
for k in dk:
|
||||
if k == "quality":
|
||||
continue
|
||||
inputs.push_back(current_data[k])
|
||||
var outputs = nn.feedforward(inputs)
|
||||
$VBoxContainer/Label.text = str(outputs[0])
|
||||
|
||||
func train_by_data():
|
||||
var data = []
|
||||
var fd = File.new()
|
||||
if fd.file_exists("res://tests/training_set.json"):
|
||||
fd.open("res://tests/training_set.json", File.READ)
|
||||
var json = JSON.parse(fd.get_as_text())
|
||||
data = json.result
|
||||
fd.close()
|
||||
for t in range(data.size() * 5):
|
||||
var inputs = []
|
||||
var dataset = data[randi() % data.size()]
|
||||
var dk = dataset.keys()
|
||||
dk.sort()
|
||||
for k in dk:
|
||||
if k == "quality":
|
||||
continue
|
||||
inputs.push_back(dataset[k])
|
||||
nn.train(inputs, [dataset["quality"]])
|
||||
|
||||
var cdirty = false
|
||||
func change_scroll_value(value, mod_name):
|
||||
characters.set_modifier_value(ch, mod_name, float(value) / 100.0)
|
||||
cdirty = true
|
||||
|
||||
func update_controls():
|
||||
for c in $VBoxContainer/s/b.get_children():
|
||||
c.queue_free()
|
||||
var mod_list = Array(characters.get_modifier_list(ch))
|
||||
mod_list.sort()
|
||||
for m in mod_list:
|
||||
var item = HBoxContainer.new()
|
||||
$VBoxContainer/s/b.add_child(item)
|
||||
var t = Label.new()
|
||||
item.add_child(t)
|
||||
t.rect_min_size.x = 100.0
|
||||
t.text = m
|
||||
var scroll = HScrollBar.new()
|
||||
item.add_child(scroll)
|
||||
scroll.rect_min_size.x = 100.0
|
||||
scroll.rect_min_size.y = 4.0
|
||||
scroll.min_value = -100.0
|
||||
scroll.max_value = 100.0
|
||||
scroll.value = characters.get_modifier_value(ch, m) * 100.0
|
||||
scroll.connect("value_changed", self, "change_scroll_value", [m])
|
||||
|
||||
func save_data(quality):
|
||||
var data = []
|
||||
var fd = File.new()
|
||||
if fd.file_exists("res://tests/training_set.json"):
|
||||
fd.open("res://tests/training_set.json", File.READ)
|
||||
var json = JSON.parse(fd.get_as_text())
|
||||
data = json.result
|
||||
fd.close()
|
||||
current_data["quality"] = quality
|
||||
data.push_back(current_data)
|
||||
fd.open("res://tests/training_set.json", File.WRITE)
|
||||
fd.store_string(JSON.print(data, "\t", true))
|
||||
fd.close()
|
||||
print(current_data.keys().size())
|
||||
func get_skeleton(base: Node):
|
||||
var queue = [base]
|
||||
var skel: Skeleton
|
||||
while queue.size() > 0:
|
||||
var item = queue[0]
|
||||
queue.pop_front()
|
||||
if item is Skeleton:
|
||||
skel = item
|
||||
break
|
||||
for c in item.get_children():
|
||||
queue.push_back(c)
|
||||
return skel
|
||||
|
||||
func get_head_pos():
|
||||
var skel = get_skeleton(ch)
|
||||
var head_id = skel.find_bone("head")
|
||||
var xform = skel.get_bone_global_pose(head_id)
|
||||
return skel.global_transform.xform(xform.origin)
|
||||
|
||||
var rotate = 0
|
||||
|
||||
func select_ok():
|
||||
train(0.5)
|
||||
save_data(0.5)
|
||||
remove()
|
||||
call_deferred("spawn")
|
||||
func select_bad():
|
||||
train(0.0)
|
||||
save_data(0.0)
|
||||
remove()
|
||||
call_deferred("spawn")
|
||||
func select_good():
|
||||
train(1.0)
|
||||
save_data(1.0)
|
||||
remove()
|
||||
call_deferred("spawn")
|
||||
func trigger_cam():
|
||||
if $r/Camera.current:
|
||||
$r/face_cam.global_transform.origin = get_head_pos() + Vector3(0, 0, 0.4)
|
||||
|
||||
$r/face_cam.make_current()
|
||||
elif $r/face_cam.current:
|
||||
$r/Camera.make_current()
|
||||
func trigger_rotate():
|
||||
rotate += 1
|
||||
match(rotate):
|
||||
0:
|
||||
$r.rotation.y = 0.0
|
||||
1:
|
||||
$r.rotation.y = PI / 2.0
|
||||
2:
|
||||
$r.rotation.y = PI
|
||||
3:
|
||||
$r.rotation.y = PI * 3.0 / 4.0
|
||||
5:
|
||||
rotate = 0
|
||||
$r.rotation.y = 0.0
|
||||
func _ready():
|
||||
$r/Camera.fov = 50.0
|
||||
$VBoxContainer/bad.connect("pressed", self, "select_bad")
|
||||
$VBoxContainer/ok.connect("pressed", self, "select_ok")
|
||||
$VBoxContainer/good.connect("pressed", self, "select_good")
|
||||
$VBoxContainer/face_trig.connect("pressed", self, "trigger_cam")
|
||||
$VBoxContainer/rotate.connect("pressed", self, "trigger_rotate")
|
||||
# characters.set_root_scene(self)
|
||||
call_deferred("init_tail")
|
||||
func init_tail():
|
||||
remove()
|
||||
spawn()
|
||||
nn = NeuralNetwork.new(current_data.keys().size(), 160, 1)
|
||||
train_by_data()
|
||||
guess()
|
||||
print(characters.get_modifier_list(ch))
|
||||
var gender = -1
|
||||
func spawn():
|
||||
if randf() >= 0.5:
|
||||
gender = 1
|
||||
else:
|
||||
gender = 0
|
||||
ch = characters.spawn_character(gender, Transform().rotated(Vector3(0, 1, 0), PI))
|
||||
current_data["gender"] = gender
|
||||
var mod_name_list = characters.get_modifier_list(ch)
|
||||
for cset in range(mod_name_list.size()):
|
||||
var _mod_id = mod_name_list[cset]
|
||||
var _mod_val = randf() * 1.5 - 0.75
|
||||
characters.set_modifier_value(ch, _mod_id, _mod_val)
|
||||
current_data[_mod_id] = _mod_val
|
||||
# characters.modify(ch)
|
||||
characters.update()
|
||||
if nn:
|
||||
guess()
|
||||
update_controls()
|
||||
|
||||
func remove():
|
||||
if ch:
|
||||
characters.remove(ch)
|
||||
func _process(delta):
|
||||
if rotate == 4:
|
||||
$r.rotation.y += delta
|
||||
if cdirty:
|
||||
characters.update()
|
||||
var mod_name_list = characters.get_modifier_list(ch)
|
||||
for cset in range(mod_name_list.size()):
|
||||
var _mod_id = mod_name_list[cset]
|
||||
current_data[_mod_id] = characters.get_modifier_value(ch, _mod_id)
|
||||
100
proto2/tests/test-collect-data.tscn
Normal file
100
proto2/tests/test-collect-data.tscn
Normal file
@@ -0,0 +1,100 @@
|
||||
[gd_scene load_steps=5 format=2]
|
||||
|
||||
[ext_resource path="res://tests/test-collect-data.gd" type="Script" id=1]
|
||||
|
||||
[sub_resource type="SpatialMaterial" id=1]
|
||||
albedo_color = Color( 0.219608, 0.32549, 0.552941, 1 )
|
||||
|
||||
[sub_resource type="CubeMesh" id=2]
|
||||
material = SubResource( 1 )
|
||||
size = Vector3( 20, 0.2, 20 )
|
||||
|
||||
[sub_resource type="BoxShape" id=3]
|
||||
extents = Vector3( 10, 0.1, 10 )
|
||||
|
||||
[node name="test-collect-data" type="Spatial"]
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="r" type="Spatial" parent="."]
|
||||
|
||||
[node name="Camera" type="Camera" parent="r"]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.2, 3 )
|
||||
|
||||
[node name="face_cam" type="Camera" parent="r"]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.4, 0.4 )
|
||||
|
||||
[node name="MeshInstance" type="MeshInstance" parent="."]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.1, 0 )
|
||||
mesh = SubResource( 2 )
|
||||
material/0 = null
|
||||
|
||||
[node name="DirectionalLight" type="DirectionalLight" parent="."]
|
||||
transform = Transform( 1, 0, 0, 0, 0.258819, 0.965926, 0, -0.965926, 0.258819, 0, 20, 0 )
|
||||
|
||||
[node name="StaticBody" type="StaticBody" parent="."]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.1, 0 )
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape" parent="StaticBody"]
|
||||
shape = SubResource( 3 )
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
anchor_bottom = 1.0
|
||||
margin_right = 78.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="good" type="Button" parent="VBoxContainer"]
|
||||
margin_right = 160.0
|
||||
margin_bottom = 20.0
|
||||
text = "Good"
|
||||
|
||||
[node name="ok" type="Button" parent="VBoxContainer"]
|
||||
margin_top = 24.0
|
||||
margin_right = 160.0
|
||||
margin_bottom = 44.0
|
||||
text = "OK"
|
||||
|
||||
[node name="bad" type="Button" parent="VBoxContainer"]
|
||||
margin_top = 48.0
|
||||
margin_right = 160.0
|
||||
margin_bottom = 68.0
|
||||
text = "Bad"
|
||||
|
||||
[node name="face_trig" type="Button" parent="VBoxContainer"]
|
||||
margin_top = 72.0
|
||||
margin_right = 160.0
|
||||
margin_bottom = 92.0
|
||||
text = "Face/Body"
|
||||
|
||||
[node name="rotate" type="Button" parent="VBoxContainer"]
|
||||
margin_top = 96.0
|
||||
margin_right = 160.0
|
||||
margin_bottom = 116.0
|
||||
text = "Rotate/Still"
|
||||
|
||||
[node name="HSeparator2" type="HSeparator" parent="VBoxContainer"]
|
||||
margin_top = 120.0
|
||||
margin_right = 160.0
|
||||
margin_bottom = 124.0
|
||||
|
||||
[node name="Label" type="Label" parent="VBoxContainer"]
|
||||
margin_top = 128.0
|
||||
margin_right = 160.0
|
||||
margin_bottom = 142.0
|
||||
text = "Unknown"
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="VBoxContainer"]
|
||||
margin_top = 146.0
|
||||
margin_right = 160.0
|
||||
margin_bottom = 150.0
|
||||
|
||||
[node name="s" type="ScrollContainer" parent="VBoxContainer"]
|
||||
margin_top = 154.0
|
||||
margin_right = 160.0
|
||||
margin_bottom = 600.0
|
||||
rect_min_size = Vector2( 160, 40 )
|
||||
size_flags_vertical = 3
|
||||
scroll_horizontal_enabled = false
|
||||
|
||||
[node name="b" type="VBoxContainer" parent="VBoxContainer/s"]
|
||||
137
proto2/tests/test-triangles.gd
Normal file
137
proto2/tests/test-triangles.gd
Normal file
@@ -0,0 +1,137 @@
|
||||
extends Node
|
||||
|
||||
var common = []
|
||||
var common_path = "characters/common"
|
||||
func load_data():
|
||||
var fd = File.new()
|
||||
fd.open("characters/common/data.json", File.READ)
|
||||
var json = fd.get_as_text()
|
||||
var json_result = JSON.parse(json)
|
||||
var json_data = json_result.result
|
||||
fd.close()
|
||||
for e in json_data.files:
|
||||
print("loading ", e)
|
||||
var load_path = "res://" + e
|
||||
var item = load(load_path)
|
||||
assert(item)
|
||||
common.push_back(item)
|
||||
print("done loading ", e)
|
||||
|
||||
func get_mesh(base: Node, mesh_name: String) -> ArrayMesh:
|
||||
var queue = [base]
|
||||
var mesh: ArrayMesh
|
||||
while queue.size() > 0:
|
||||
var item = queue[0]
|
||||
queue.pop_front()
|
||||
if item is MeshInstance && item.name == mesh_name && item.mesh:
|
||||
mesh = item.mesh
|
||||
break
|
||||
for c in item.get_children():
|
||||
queue.push_back(c)
|
||||
return mesh
|
||||
|
||||
func _ready():
|
||||
print("loading data")
|
||||
load_data()
|
||||
print("data loaded")
|
||||
var fd = File.new()
|
||||
fd.open("characters/blendmaps.bin", File.WRITE);
|
||||
var bcount = 0
|
||||
for c in common:
|
||||
var obj = c.instance()
|
||||
for cm in ["base", "tights_helper", "robe_helper", "skirt_helper"]:
|
||||
print(obj.name, " ", cm)
|
||||
var mesh: ArrayMesh = get_mesh(obj, cm)
|
||||
bcount += mesh.get_blend_shape_count()
|
||||
fd.store_32(bcount)
|
||||
var deflate_size = 0
|
||||
var rle_size = 0
|
||||
for c in common:
|
||||
var obj = c.instance()
|
||||
print(obj.name)
|
||||
for cm in ["base", "tights_helper", "robe_helper", "skirt_helper"]:
|
||||
print(cm)
|
||||
var mesh: ArrayMesh = get_mesh(obj, cm)
|
||||
var base_array = mesh.surface_get_arrays(0)
|
||||
assert(base_array.size() > 0)
|
||||
var shape_arrays = mesh.surface_get_blend_shape_arrays(0)
|
||||
assert(shape_arrays.size() > 0)
|
||||
for x in range(mesh.get_blend_shape_count()):
|
||||
var triset = TriangleSet.new()
|
||||
var shape_name = mesh.get_blend_shape_name(x)
|
||||
print(obj.name, " ", shape_name, " ", x)
|
||||
var shape_array = shape_arrays[x]
|
||||
triset.create_from_array_shape(base_array, shape_array)
|
||||
var img = Image.new()
|
||||
var imgn = Image.new()
|
||||
img.create(512, 512, false, Image.FORMAT_RGBA8)
|
||||
imgn.create(512, 512, false, Image.FORMAT_RGBA8)
|
||||
triset.draw(img, imgn, 1)
|
||||
var rledata = triset.get_data(img, imgn)
|
||||
triset.save(fd, cm.replace("_helper", "") + ":" + shape_name, img, imgn)
|
||||
# var minp = triset.get_min()
|
||||
# var maxp = triset.get_max()
|
||||
# var min_normal = triset.get_min_normal()
|
||||
# var max_normal = triset.get_max_normal()
|
||||
# fd.store_pascal_string(cm.replace("_helper", "") + ":" + shape_name)
|
||||
# fd.store_float(minp.x)
|
||||
# fd.store_float(minp.y)
|
||||
# fd.store_float(minp.z)
|
||||
# fd.store_float(maxp.x)
|
||||
# fd.store_float(maxp.y)
|
||||
# fd.store_float(maxp.z)
|
||||
# fd.store_32(img.get_width())
|
||||
# fd.store_32(img.get_height())
|
||||
# fd.store_32(img.get_format())
|
||||
# fd.store_32(img.get_data().size())
|
||||
# var imgbuf = img.get_data().compress(File.COMPRESSION_FASTLZ)
|
||||
# fd.store_32(imgbuf.size())
|
||||
# fd.store_buffer(imgbuf)
|
||||
# fd.store_float(min_normal.x)
|
||||
# fd.store_float(min_normal.y)
|
||||
# fd.store_float(min_normal.z)
|
||||
# fd.store_float(max_normal.x)
|
||||
# fd.store_float(max_normal.y)
|
||||
# fd.store_float(max_normal.z)
|
||||
# fd.store_32(imgn.get_width())
|
||||
# fd.store_32(imgn.get_height())
|
||||
# fd.store_32(imgn.get_format())
|
||||
# fd.store_32(imgn.get_data().size())
|
||||
# var imgnbuf = imgn.get_data().compress(File.COMPRESSION_FASTLZ)
|
||||
# print("rle size = ", rledata.size(), ", deflate size = ", imgbuf.size() + imgnbuf.size())
|
||||
# rle_size += rledata.size()
|
||||
# deflate_size += imgbuf.size() + imgnbuf.size()
|
||||
# fd.store_32(imgnbuf.size())
|
||||
# fd.store_buffer(imgnbuf)
|
||||
img.save_png("res://" + common_path + "/" + cm + "_" + shape_name + ".png")
|
||||
imgn.save_png("res://" + common_path + "/" + cm + "_" + shape_name + "_normal.png")
|
||||
fd.close()
|
||||
print("saved")
|
||||
var c = characters.characters[1]
|
||||
var obj = c.instance()
|
||||
print(obj.name)
|
||||
print("body")
|
||||
var mesh_target: ArrayMesh = load("res://characters/accessory/female/body/body_default.mesh")
|
||||
print("base")
|
||||
var mesh_base: ArrayMesh = get_mesh(common[0].instance(), "base")
|
||||
assert(mesh_target)
|
||||
assert(mesh_base)
|
||||
var base_array = mesh_base.surface_get_arrays(0)
|
||||
var target_array = mesh_target.surface_get_arrays(0)
|
||||
var triset = TriangleSet.new()
|
||||
triset.create_from_mesh_difference(base_array, 1, target_array, 1)
|
||||
var img = Image.new()
|
||||
var imgn = Image.new()
|
||||
img.create(512, 512, false, Image.FORMAT_RGBA8)
|
||||
imgn.create(512, 512, false, Image.FORMAT_RGBA8)
|
||||
triset.draw(img, imgn, 1)
|
||||
img.save_png("res://" + common_path + "/female.png")
|
||||
imgn.save_png("res://" + common_path + "/female_normal.png")
|
||||
var minp = triset.get_min()
|
||||
var maxp = triset.get_max()
|
||||
var min_normal = triset.get_min_normal()
|
||||
var max_normal = triset.get_max_normal()
|
||||
print([minp, maxp, min_normal, max_normal])
|
||||
print("complete")
|
||||
print("deflate size: ", deflate_size, " rle size: ", rle_size)
|
||||
|
||||
6
proto2/tests/test-triangles.tscn
Normal file
6
proto2/tests/test-triangles.tscn
Normal file
@@ -0,0 +1,6 @@
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://tests/test-triangles.gd" type="Script" id=1]
|
||||
|
||||
[node name="test-triangles" type="Node"]
|
||||
script = ExtResource( 1 )
|
||||
12
proto2/tests/test_baricentric.gd
Normal file
12
proto2/tests/test_baricentric.gd
Normal file
@@ -0,0 +1,12 @@
|
||||
extends Node
|
||||
|
||||
func _ready():
|
||||
var dnatool : = DNATool.new()
|
||||
var pt : = Vector3(0.25, 0.25, 3)
|
||||
var p1 : = Vector3(0, 0, 0)
|
||||
var p2 : = Vector3(1, 0, 0)
|
||||
var p3 : = Vector3(0, 1, 0)
|
||||
var bc = dnatool.get_baricentric(pt, p1, p2, p3)
|
||||
print(bc)
|
||||
print([1.0 - bc.x, 1.0 - bc.y, 1.0 - bc.z])
|
||||
print(p1 * bc.x + p2 * bc.y + p3 * bc.z)
|
||||
6
proto2/tests/test_baricentric.tscn
Normal file
6
proto2/tests/test_baricentric.tscn
Normal file
@@ -0,0 +1,6 @@
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://tests/test_baricentric.gd" type="Script" id=1]
|
||||
|
||||
[node name="test_baricentric" type="Node"]
|
||||
script = ExtResource( 1 )
|
||||
41
proto2/tests/test_character_refactor.gd
Normal file
41
proto2/tests/test_character_refactor.gd
Normal file
@@ -0,0 +1,41 @@
|
||||
extends Spatial
|
||||
|
||||
var instances = []
|
||||
var genders = ["male", "female"]
|
||||
|
||||
var count = 10
|
||||
var x = -float(count - 1) / 2.0 * 0.6
|
||||
|
||||
func create_ch():
|
||||
for k in range(count):
|
||||
var instance = CharacterInstanceList.create(genders[randi() % genders.size()], Transform().translated(Vector3(x, 0, 0)).rotated(Vector3(0, 1, 0), PI), {})
|
||||
var ml = CharacterInstanceList.get_base_modifier_list()
|
||||
print(ml)
|
||||
for k in ml:
|
||||
CharacterInstanceList.set_mod_value(instance, k, randf() * 0.5)
|
||||
instances.push_back(instance)
|
||||
x += 0.6
|
||||
CharacterInstanceList.update()
|
||||
print("OK")
|
||||
|
||||
|
||||
func _ready():
|
||||
seed(OS.get_unix_time())
|
||||
CharacterGenderList.config()
|
||||
call_deferred("create_ch")
|
||||
|
||||
var quit_delay = 1.4
|
||||
func _process(delta):
|
||||
quit_delay -= delta
|
||||
if quit_delay <= 0.0:
|
||||
get_tree().quit()
|
||||
elif instances.size() < 200:
|
||||
var instance = CharacterInstanceList.create(genders[randi() % genders.size()], Transform().translated(Vector3(x, 0, 0)).rotated(Vector3(0, 1, 0), PI), {})
|
||||
var ml = CharacterInstanceList.get_base_modifier_list()
|
||||
for k in ml:
|
||||
CharacterInstanceList.set_mod_value(instance, k, randf() * 0.5)
|
||||
instances.push_back(instance)
|
||||
print(instances.size())
|
||||
x += 0.6
|
||||
CharacterInstanceList.update()
|
||||
|
||||
28
proto2/tests/test_character_refactor.tscn
Normal file
28
proto2/tests/test_character_refactor.tscn
Normal file
@@ -0,0 +1,28 @@
|
||||
[gd_scene load_steps=4 format=2]
|
||||
|
||||
[ext_resource path="res://tests/test_character_refactor.gd" type="Script" id=1]
|
||||
|
||||
[sub_resource type="CubeMesh" id=1]
|
||||
size = Vector3( 20, 0.1, 20 )
|
||||
|
||||
[sub_resource type="ConcavePolygonShape" id=2]
|
||||
data = PoolVector3Array( -10, 0.05, 10, 10, 0.05, 10, -10, -0.05, 10, 10, 0.05, 10, 10, -0.05, 10, -10, -0.05, 10, 10, 0.05, -10, -10, 0.05, -10, 10, -0.05, -10, -10, 0.05, -10, -10, -0.05, -10, 10, -0.05, -10, 10, 0.05, 10, 10, 0.05, -10, 10, -0.05, 10, 10, 0.05, -10, 10, -0.05, -10, 10, -0.05, 10, -10, 0.05, -10, -10, 0.05, 10, -10, -0.05, -10, -10, 0.05, 10, -10, -0.05, 10, -10, -0.05, -10, 10, 0.05, 10, -10, 0.05, 10, 10, 0.05, -10, -10, 0.05, 10, -10, 0.05, -10, 10, 0.05, -10, -10, -0.05, 10, 10, -0.05, 10, -10, -0.05, -10, 10, -0.05, 10, 10, -0.05, -10, -10, -0.05, -10 )
|
||||
|
||||
[node name="test_character_refactor" type="Spatial"]
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="Camera" type="Camera" parent="."]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.3, 4 )
|
||||
fov = 50.0
|
||||
|
||||
[node name="MeshInstance" type="MeshInstance" parent="."]
|
||||
mesh = SubResource( 1 )
|
||||
material/0 = null
|
||||
|
||||
[node name="StaticBody" type="StaticBody" parent="MeshInstance"]
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape" parent="MeshInstance/StaticBody"]
|
||||
shape = SubResource( 2 )
|
||||
|
||||
[node name="DirectionalLight" type="DirectionalLight" parent="."]
|
||||
transform = Transform( 1, 0, 0, 0, -1.62921e-07, 1, 0, -1, -1.62921e-07, 0, 20, 0 )
|
||||
6402
proto2/tests/training_set.json
Normal file
6402
proto2/tests/training_set.json
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user